python-在Django的多对多关系中是否有一种优雅的建模和表示一对多关系的方法?
作者:互联网
我对似乎不太复杂的某些内容感到有些困惑.这是我的模型:
class Team(models.Model):
name = models.CharField('team name', max_length=200, unique=True)
class QualityStream(models.Model):
name = models.CharField('quality stream name', max_length=200, unique=True)
team = models.ManyToManyField(Team)
class Milestone(models.Model):
name = models.CharField('milestone name', max_length=200)
quality_stream = models.ForeignKey(QualityStream)
team = models.ForeignKey(Team)
如您所见,一个团队可以有几个预定义的质量流,以及要实现的几个里程碑,这些里程碑确实属于质量流.
这是我的看法:
<p>{{team.name}}</p>
{% for stream in team.qualitystream_set.all %}
<p>{{stream.name}}</p>
{% for milestone in team.milestone_set.all %}
{% if milestone.quality_stream.id == stream.id %}
<p>{{milestone.name}}</p>
{% endif %}
{% endfor %}
{% endfor %}
想法是显示团队,与团队相关联的质量流以及按质量流分组的每个里程碑:
Team
Quality Stream 1
Milestone 1 for Quality Stream 1
Milestone 2 for Quality Stream 1
Quality Stream 2
Milestone 1 for Quality Stream 2
Milestone 2 for Quality Stream 2
该代码可以很好地工作,但是我对每个Quality流的所有里程碑进行循环浏览并不太舒服.我想一定有更好的方法来实现这一目标.有任何想法吗?
解决方法:
每当您认为必须像自己一样执行多个递减循环时,请考虑是否可以从另一端解决问题.
正如@Pathetique指出的那样,以下链接显示了如何最大程度地减少正在执行的查询:
该链接中的亮点是select_related(仅适用于ForeignKeys)和prefetch_related(仅适用于ManyToManyFields).
因为您是从“我有一组团队,现在我想显示与这些团队相关的所有数据”的角度来解决此问题的,所以您无法使用任何可用的优化,因为团队没有ForeignKeys或ManyToManyFields.
相反,您可以像这样处理问题:“我想按团队然后按质量流显示所有里程碑”.由于Milestone类可以访问所需的所有数据,因此它使得查询集的构造非常容易,仅生成一个查询.
def my_view(request):
queryset = Milestone.objects.select_related(
'team', 'quality_stream'
).order_by(
'team__name', 'quality_stream__name'
) # a single query to fetch all teams + streams + milestones
return render_to_response('/your/template.html',
{ 'milestones':queryset },
context_instance=RequestContext(request)
)
现在,您的模板将打破您构建它的方式.这就是我前面提到的问题的定义所在.您拥有所有里程碑,但是您希望按团队然后按质量流对它们进行分组.查询集的排序现在对我们有所帮助,因为我们可以遍历所有里程碑,并检查我们是否需要新团队或新质量流.
# your template
{% for milestone in milestones %}
{% ifchanged %} <p> {{ milestone.team.name }} </p> {% endifchanged %}
{% ifchanged %} <p> {{ milestone.quality_stream.name }} </p> {% endifchanged %}
<p> {{ milestone.name }} </p>
{% endfor %}
上面的模板使用ifchanged模板标签,该标签似乎正是为此目的而设计的.
标签:django-queryset,grouping,python,django 来源: https://codeday.me/bug/20191031/1973343.html