在Django模板中显示复杂的词典

时间:2012-10-20 14:45:05

标签: django django-templates

我在Ubuntu 12.04上使用Django 1.4和Python 2.7。

我有一个模板,我想填写有关项目开发人员的信息。

每位开发人员都将显示以下信息:

type
title
first_name
last_name
skills

我遇到的麻烦是每个开发人员都有很多与之相关的技能。

我已经创建了这样的模型:

class DevSkills(models.Model):
    dev = models.ForeignKey(User)

    skill = models.CharField(max_length = 200)

我正在尝试创建一个将填充字典的视图,以便我可以遍历每个开发人员,显示他们的信息,然后遍历每个技能(一次显示一个)。

以下是观点:

def developers(request):
    """
    ..  function:: developers()

        Provide the page that shows the developer credentials

        :param request: Django Request object
    """
    devs = User.objects.filter(is_staff = True)
    dev_info = {}
    for dev in devs:
        dev_info.update(createDevDisplayDict(dev))
    data = { 'user' : request.user }
    data.update({ 'devs' : dev_info })

    return render_to_response("developers.html", data)

我已指定is_staff中的User字段,表示该用户是开发人员。

我创建了一个简单的实用程序,可以帮助我填充嵌入的词典,以便我可以遍历它们:

def createDevDisplayDict(user):
    """
    ..  function:: createDevDisplayDict()

        Create a dictionary for showcasing the developer

        :param user: developer who we are working with
    """

    userProfile = UserProfile.objects.get(user = user)
    devSkills = DevSkills.objects.filter(dev = user) 
    dev_dict = {}
    user_dict = { 'dev_type'        : userProfile.dev_type,
                  'title'           : userProfile.title,
                  'first_name'      : user.first_name,
                  'last_name'       : user.last_name,
                }
    dev_dict.update(user_dict)

    skill_dict = {}
    for skill in devSkills:
        skill_dict.upate({ 'skill' : skill.skill })

    dev_dict.update(skill_dict)
    return dev_dict

我的目的是遍历每个开发人员,创建一个“超级”字典来包含他们的user_dict字典(基于他们的User信息)并为每个字典添加一个字典他们的技能。然后,回到模板中,我想循环遍历“超级”字典,以便它们呈现如下内容:

James Taylor
Project Lead
Software Developer
    • Django
    • Python
    • JavaScript
    • JQuery

Elizabeth Norton
Design Lead
Graphic Designer
    • Edge
    • Adobe Photoshop
    • Adobe Illustrator
    • CSS

以下是我正在尝试使用的模板:

{% extends "base.html" %}

{% block content %}
<div>
    <p>Our Developers</p>
</div>
    {% for dev in devs %}
        {{ dev.user_dict.first_name }} {{ dev.user_dict.last_name }}
        {{ dev.user_dict.title }}
        {{ dev.user_dict.dev_type }}

        <ul> 
        {% for skill in dev.skill_dict %}
            <li>skill.skill</li>
        {% endfor %}
        </ul>
    {% endfor %}
{% endblock %}

当我看到页面时,它看起来像这样:

Our Developers

是的......没有任何人填充。有什么建议吗?

更新1: 我根据iMom0的建议修改了我的实用程序。我现在使用列表来包含每项技能。像这样:

def createDevDisplayDict(user):
    """
    ..  function:: createDevDisplayDict()

        Create a dictionary for showcasing the developer

        :param user: developer who we are working with
    """

    userProfile = UserProfile.objects.get(user = user)
    devSkills = DevSkills.objects.filter(dev = user) 
    dev_dict = {}
    user_dict = { 'dev_type'        : userProfile.dev_type,
                  'title'           : userProfile.title,
                  'first_name'      : user.first_name,
                  'last_name'       : user.last_name,
                }
    dev_dict.update(user_dict)

    skills = []
    for skill in devSkills:
        skills.append(skill.skill)

    skill_dict = {'skill' : skills}

    dev_dict.update(skill_dict)
    return dev_dict

我可以看到这样做的价值 - 事实上,它更加直观,而且我认为我在另一方面做得太难了。但我的模板仍显示裸露。 :(

更新2:

我知道我现在正在写道。我在视图中添加了一些日志记录:

devs = User.objects.filter(is_staff = True, is_superuser = False)
dev_info = {}
for dev in devs:
    dev_info.update(createDevDisplayDict(dev))

for key in dev_info:
    for sub_key in dev_info[key]:
        logfile.write('{0} = {1}\n'.format(sub_key, dev_info[key][sub_key]))

日志文件显示:

skills = [u'Java', u'Perl', u'C++', u'Python', u'Django']
dev_type = Software Developer
first_name = Rico
last_name = Cordova
title = Owner

所以,它必须是我在模板中调用它的方式,对吧?

更新3:

我意识到我正在断开user_dict及其skills的连接。所以我稍微修改了实用程序,将它们放入一个字典中。

## Create a logging object
userProfile = UserProfile.objects.get(user = user)
devSkills = DevSkills.objects.filter(dev = user) 
dev_dict = {}
user_dict = { 'dev_type'        : userProfile.dev_type,
              'title'           : userProfile.title,
              'first_name'      : user.first_name,
              'last_name'       : user.last_name,
            }

skills = []
for skill in devSkills:
    skills.append(skill.skill)

user_dict.update({ 'skills' : skills })

dev_dict['user_dict'] = user_dict
return dev_dict

在我看来,这是一个更好的解决方案。我仍然无法访问模板中的user_dict信息。 :(

3 个答案:

答案 0 :(得分:2)

你可以使用Django的ORM功能让这更容易(而且,我们会看到,获得更好的性能),这是一个很棒的功能!

型号代码

class DevSkill(models.Model):
    dev     = models.ForeignKey(UserProfile, related_name = 'skill_set')
    skill   = models.CharField(max_length = 200)

我们改变了两件事:

  • 使用UserProfile ForeignKey代替用户将简化其余代码。由于您有UserProfile&lt; - &gt;无论如何User映射,这不会成为一个问题。
  • 我们添加了related_name属性,以便任何UserProfile对象现在都有skill_set属性,该属性存储DevSkills的列表。

(请注意,related_name不是必需的,如果您没有设置,Django将创建一个通用的modelname_set属性。 此外,DevSkill应该是单数,对象是单一技能!

我还希望您对UserProfile有以下内容,并假设您创建了代码。如果不这样做,你需要适应。

class UserProfile(models.Model):
    user     = models.OneToOneField(User)
    title    = models.CharField(max_length = 40)
    dev_type = # W/E you want

在视图中:

devs = UserProfile.objects.all() # Or W/E queryset would fit.
# Pass context & all.

在模板中:

{% extends "base.html" %}

{% block content %}
<div>
    <p>Our Developers</p>
</div>
    {% for dev in devs %}
        {{ dev.user.first_name }} {{ dev.user.last_name }}
        {{ dev.title }}
        {{ dev.dev_type }}

        <ul> 
        {% for skill in dev.skill_set.all %}
            <li>skill.skill</li>
        {% endfor %}
        </ul>
    {% endfor %}
{% endblock %}

效果

请注意,此代码(您现在正在使用的代码)将绝对会破坏性能。实际上,我们正在为每个用户进行多次查询(为他们的用户和他们的DevSkills访问数据库)。

但这不是问题,我们可以使用ORM的select_relatedprefetch_related功能来解决这个问题:

devs = UserProfile.objects.select_related('user').prefetch_related('skill_set').all()
这样,我们只执行两个查询,一个用于UserProfile - &gt; UserDevSkill的一个,加入是用Python完成的,但你不应该关心它,Django会为你做。

请注意prefetch_related是Django 1.4的功能。


脚注:UserProfile内容在Django 1.5中消失,请查看!

答案 1 :(得分:1)

dict.update始终覆盖dict的值

In [2]: d = {'key': 'value'}

In [3]: d.update({'key': 'value1'})

In [4]: d
Out[4]: {'key': 'value1'}

相反,您应该使用listlist.append

您的模板不知道user_dict是什么,更正,

dev_dict['user_dict'] = user_dict

答案 2 :(得分:0)

这是我的新概念 - 模板中的dict.items。以下是我能够展示我想要的内容。

{% extends "base.html" %}

{% block content %}
<div>
    <p>Our Developers</p>
</div>
    {% for key, value in devs.items %}
        {{ value.first_name }} {{ value.last_name }} <br>
        {{ value.title }} <br>
        {{ value.dev_type }} <br>
        <ul> 
        {% for skill in value.skills %}
            <li>{{ skill }}</li>
        {% endfor %}
        </ul>
    {% endfor %}
{% endblock %}