views:

48

answers:

1

I have two models, EqTD (EquivalentTextDescription) and location. EqTD has a manytomany relation to location. I need to produce a list of all EqTDs ordered by location name ('name' is a field in the location model). I'm getting the queryset of EqTDs thus:

tEqTDs = EqTD.objects.order_by('location__name')

which I'm hoping will produce duplicates, if they exist, when the same EqTD is linked to more than one location.

In the HTML template, I want to use {% ifchanged %} to put a header with the location name above each group of EqTDs. However, this code:

{% for eqtd in object_list %}
 {% ifchanged %}
   <tr><td  colspan="2"><h3>
   {{ eqtd.location.name }} 
   </h3></td></tr>
 {% endifchanged %}
  ...
{% endfor %}

outputs nothing. I realized that eqtd.location.name is probably meaningless. Which location?

It was suggested that I use annotate() to add the location name to each item in the queryset, like this:

tEqTDs = EqTD.objects.annotate( eqtd_loc = 'location__name').order_by('eqtd_loc')

but this results in an Attribute Error: 'str' object has no attribute 'lookup'.

Is annotate() is expecting a callable?

This must be a common pattern. What's the key?

A: 

i don't know that ordering on a many to many is a great idea. see here

instead, it may be a better idea to query all your locations, then iterate over them, print a header, and then iterate over their EqTD objects in EqTD_set.all()

{% for location in object_list %}
   <tr><td  colspan="2"><h3>
   {{ location.name }} 
   </h3></td></tr>
    {% for eqtd in location.eqtd_set.all %}
        ...
    {% endfor %}
{% endfor %}
Brandon H
I was hoping to maintain a parallelism to an alternative list (by another attribute of EqTD), as well as being able to paginate the result. I don't think I'll be able to paginate with this solution, will I? I wonder, can I concatenate query sets in the view?
Though it might not be the best solution, I took the hint supplied by Brandon and—in order to get the pagination I needed—constructed a list of EqTD dicts in the view function with location.eqtd_set.all.values(), adding a 'location' key to each EqTD. There it was: a paginated list of all EqTDs broken out by location, with duplicates as required.