我的数据模型很简单:
class Neighborhood(models.Model):
name = models.CharField(max_length = 50)
slug = models.SlugField()
class Location(models.Model):
company = models.ForeignKey(Company)
alt_name = models.CharField()
neighborhoods = models.ManyToManyField(Neighborhood)
我想在我的网站上提供一个页面,列出他们所在地区的所有位置。如果它是单数,我认为{% regroup %}
应用了邻域名称{% ifchanged %}
将是我需要的所有内容,但在我的情况下,如果它是m2m,我不知道这是怎么回事。一个位置可能有多个邻域,所以我希望它们在每个匹配的邻域下面冗余显示。
我也知道FOO_set
,但这是每个对象;我想加载整个数据集。
最终结果(在模板中)应该是这样的:
Alameda
Crazy Thai
Castro
Kellys Burgers
Pizza Orgasmica
Filmore
Kellys Burgers
Some Jazz Bar
Mission
Crazy Thai
Elixir
...
模板语法(理想情况下?)看起来像:
{% for neighborhood in neighborhood_list %}
{% ifchanged %}{{ neighborhood.name }}{% endifchanged %}
{% for location in neighborhood.restaurants.all %}
{{ location.name }}
{% endfor %}
{% endfor %}
答案 0 :(得分:1)
创建另一个定义m2m关系的模型:
class ThroughModel(models.Model):
location = models.ForeignKey('Location')
neighborhood = models.ForeignKey('Neighborhood')
并将其用作m2m字段的through
模型:
class Location(models.Model):
...
neighborhoods = models.ManyToManyField(Neighborhood, through='ThroughModel')
然后你可以把你所有的社区分类:
ThroughModel.objects.select_related().order_by('neighborhood__name')
这是未经测试的。
或者,如果您无法更改数据库,只需执行原始SQL连接。
答案 1 :(得分:1)
我只是以昂贵的方式做到这一点并将结果缓存在我的头上。您的模板示例可以正常工作,直到性能成为每个X缓存超时生成一个页面的问题。
如果结果集足够小,你也可以在python中完成它:
# untested code - don't have your models
from collections import defaultdict
results = defaultdict(list)
for location_m2m in Location.neighborhoods.through.objects.all() \ # line wrap
.select_related('neighborhood', 'location', 'location__company__name'):
if location_m2m.location not in results[location_m2m.neighborhood]:
results[location_m2m.neighborhood].append(location_m2m.location)
# sort now unique locations per neighborhood
map(lambda x: x.sort(key=lambda x: x.location.company.name), results.values())
# sort neighborhoods by name
sorted_results = sorted(results.items(), key=lambda x:x[0].name)