On Tue, Dec 21, 2010 at 9:48 PM, Dopster <ken.kyhu...@gmail.com> wrote:
> 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)
>
> How do I get an output of the following?
>
> GroupA: John, Stacy, Pete
> GroupB: Bob, Bill, Mary
>
> I want to cycle through the groups and then output the people in each group.
> In rough pseudo-code:
>
> groups = Group.objects.all()
>
> for g in groups:
>   print g.group_name, ": "
>   for p in g.person_set.all:
>      print p.person
>
> However, this leads to a query being run for each person in order to access
> the person's name, which I find to be really unnecessary. I only want to run
> one query per group -- will I have to use raw SQL to do this? My initial
> thought was to run a query that returns all the people in a group, and then
> cycling through the queryset to append the names into a list and then
> attaching the list to the project object.
>

Are you sure? What you have written should result in precisely what
you asked for, 1 query to get the list of groups, 1 query per group to
get the list of users. Your pseudo-code is a little wrong (for p in
g.person_set.all(): print p.person - isn't p already a person? :), but
if I correct that (and use standard contrib.auth models):

>>> from django.contrib.auth.models import User, Group
>>> from django.db import connection
>>> for g in Group.objects.all():
...   print g.name, ':'
...   for u in g.user_set.all():
...     print u.get_full_name()
...
...
>>> pprint(connection.queries)
[{'sql': u'SELECT `auth_group`.`id`, `auth_group`.`name` FROM `auth_group`',
  'time': '0.000'},
 {'sql': u'SELECT `auth_user`.`id`, `auth_user`.`username`,
`auth_user`.`first_name`, `auth_user`.`last_name`,
`auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`,
`auth_user`.`is_active`, `auth_user`.`is_superuser`,
`auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user`
INNER JOIN `auth_user_groups` ON (`auth_user`.`id` =
`auth_user_groups`.`user_id`) WHERE `auth_user_groups`.`group_id` = 1
',
  'time': '0.002'},
 {'sql': u'SELECT `auth_user`.`id`, `auth_user`.`username`,
`auth_user`.`first_name`, `auth_user`.`last_name`,
`auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`,
`auth_user`.`is_active`, `auth_user`.`is_superuser`,
`auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user`
INNER JOIN `auth_user_groups` ON (`auth_user`.`id` =
`auth_user_groups`.`user_id`) WHERE `auth_user_groups`.`group_id` = 2
',
  'time': '0.007'},
 {'sql': u'SELECT `auth_user`.`id`, `auth_user`.`username`,
`auth_user`.`first_name`, `auth_user`.`last_name`,
`auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`,
`auth_user`.`is_active`, `auth_user`.`is_superuser`,
`auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user`
INNER JOIN `auth_user_groups` ON (`auth_user`.`id` =
`auth_user_groups`.`user_id`) WHERE `auth_user_groups`.`group_id` = 3
',
  'time': '0.006'}]


On Tue, Dec 21, 2010 at 9:59 PM, Javier Guerra Giraldez
<jav...@guerrag.com> wrote:
> in the view:
> persons = Person.objects.all().order_by('group')
>
> in the template:
> {% for p in persons %}
>  {% ifchanged p.group %}
>      {{p.group}}:
>  {%endifchanged%}
>  {{p.name}}
> {% endfor %}
>
>

No, that's even worse - that is one query to get the list of people,
and one query per person to build their group model object. If the
ifchanged checked 'p.group_id' instead of  'p.group', then that avoid
unnecessarily instantiating the group object, and would cut it down to
num_groups + 1 queries.

Cheers

Tom

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to