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.