编程语言
首页 > 编程语言> > python-在Django的多对多关系中是否有一种优雅的建模和表示一对多关系的方法?

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指出的那样,以下链接显示了如何最大程度地减少正在执行的查询:

https://docs.djangoproject.com/en/1.5/topics/db/optimization/#retrieve-everything-at-once-if-you-know-you-will-need-it

该链接中的亮点是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