2

我在 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字段 fromUser以指示用户是开发人员。

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

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模板中的信息。:(

4

3 回答 3

2

您可以使用 Django 的 ORM 功能来简化此操作(并且,我们将看到,获得更好的性能),这是一个很棒的功能!

型号代码

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

我们改变了两件事:

  • 使用 aUserProfile ForeignKey而不是 user 将简化其余代码。由于无论如何您都有UserProfile<->User映射,因此这不会成为问题。
  • 我们添加了一个related_name属性,以便任何UserProfile对象现在都有一个skill_set属性来存储它的DevSkills.

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

我还希望您拥有以下 for 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 访问数据库)。

不过这不是问题,我们可以使用 ORMselect_relatedprefetch_related特性来解决这个问题:

devs = UserProfile.objects.select_related('user').prefetch_related('skill_set').all()
这样,我们只做两个查询,一个用于UserProfile->User和一个用于DevSkill's,连接是在 Python 中完成的,但你不应该关心这个,Django 会为你做。

请注意,这prefetch_related是 Django 1.4 的功能。


脚注:这些UserProfile东西在 Django 1.5 中消失了,看看吧!

于 2012-10-20T15:58:46.120 回答
1

dict.update总是覆盖 dict 的值

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

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

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

相反,您应该使用listand list.append

而且你的模板不知道是什么user_dict,纠正一下,

dev_dict['user_dict'] = user_dict
于 2012-10-20T14:50:52.583 回答
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 %}
于 2012-10-20T15:45:20.890 回答