How do I generate and display Django querysets fro

2019-05-03 11:33发布

For example, let's say I have the following models:

class Group(models.Model):
    group_name = models.CharField(max_length=20)

class Person(models.Model):
    group = models.ForeignKey(Group)
    name = models.CharField(max_length=50)

I want to list all groups, and for each group list the people in the group.

Group A: Person1, Person2, Person3
Group B: Person4, Person5, Person6

I get stuck at Group.objects.all(), which will only return a queryset containing the Group objects that I can cycle through in the template. I don't know how to cycle through the people in each group though. Help?

groups = Group.objects.all()

{% for g in groups %}
    g.group_name:
   << Need an inner loop here to cycle through the people in each group? >>
{% endfor %}

3条回答
Rolldiameter
2楼-- · 2019-05-03 12:04

You can use the builtin regroup tag:

Template:

{% regroup people by group as people_by_group %}
{% for group in people_by_group %}
    {{ group.grouper.group_name }}
    {% for person in group.list %}
        {{ person }}
    {% endfor %}
{% endfor %}

Context:

{'people': Person.objects.all().select_related('group').order_by('group')}

This won't list empty groups, but you can build a similar strucutre in your own view, for example:

groups = list(Group.objects.all())
groups_map = dict((g.pk, g) for g in groups)
for g in groups:
    g.person_cache = []
for person in Person.objects.all():
    if person.group_id is not None:
        groups_map[person.group_id].person_cache.append(person)
del groups_map
# ``groups`` now contains a list suitable for your template

This way you make only two queries. Using a related manager in a loop will produce number_of_groups+1 queries.

查看更多
聊天终结者
4楼-- · 2019-05-03 12:15

You need to actually query for the people instead of the group.

people = Person.objects.select_related().order_by('group')
{% for person in people %}
  {% ifchanged person.group %}
    {{ person.group }}
  {% endifchanged %}
  {{ person }}
{% endfor %}

This does one query for all people and their related groups, ordered by group. The ifchanged in the template recognizes when you've moved on to a new group and prints it out.

Hope that helps.

查看更多
登录 后发表回答