How to produce a list ordered by a manyToMany field and display it using {% ifchanged %} in a template?
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开发者_Python百科 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?
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 %}
精彩评论