通过特定的 ManyToMany 对象订购 Django QuerySet
Posted
技术标签:
【中文标题】通过特定的 ManyToMany 对象订购 Django QuerySet【英文标题】:Order a Django QuerySet by a specific ManyToMany Object 【发布时间】:2014-06-20 06:26:06 【问题描述】:我有两个类 - Arzt 和 Fachbereich - 通过 ArztFachbereich 以多对多关系相关。
class Fachbereich(FachbereichUndArztFachbereiche):
name = models.CharField(unique=True, max_length=100)
class Arzt(models.Model):
name = models.CharField(max_length=500)
fachbereich = models.ManyToManyField(Fachbereich, through="ArztFachbereich")
class ArztFachbereich(FachbereichUndArztFachbereiche):
arzt = models.ForeignKey(Arzt)
fachbereich = models.ForeignKey(Fachbereich)
note = models.FloatField()
我知道如何获得按 Arzt 的最小注释排序的结果。
Arzt.objects.annotate(best_note=Min("arztfachbereich__note")).order_by("best_note")
但接下来我首先通过 Fachbereich-ID (fb_id) 过滤 Arzt。现在我不需要最低限度的注释或聚合的东西,而是这个特定的 ArztFachbereich 的注释。
澄清我在说什么: 像这样的东西......但我不知道如何在 django 中做到这一点。
aerzte = Arzt.objects.filter(fachbereich=fb_id)
aerzte.order_by("arztfachbereich__note"
WHERE arztfachbereich__fachbereich ==
Fachbereich.objects.get(id=fb_id))
或者我想到的另一种方式:
aerzte = Arzt.objects.filter(fachbereich=fb_id)
aerzte.annotate(specific=ArztFachbereich.objects.get(arzt=self, fachbereich__id=fb_id)
aerzte.order_by("specific")
但我显然无法通过自我声明访问 arzt...
【问题讨论】:
【参考方案1】:如果我理解正确,这应该可以:
Arzt.objects.filter(arztfachbereich__fachbereich_id=fb_id)
.order_by("arztfachbereich__note")
有关此关系的任何查询都将在ArztFachbereich
表上运行(可能JOIN
ed 到Arzt
和Fachbereich
表,具体取决于查询)。在这里,filter()
将对应于 SQL WHERE
子句,该子句将行限制为特定值 fachbereich_id
,然后 order_by
按 note
值对剩余的行进行排序。
我认为您的困惑来自于我们正在查询 Artz
模型这一事实。这是否更有意义:ArztFachbereich.objects.filter(fachbereich_id=fb_id).order_by("note")
?这两个语句本质上是等价的,但是过滤Artz
让您最终得到Artz
对象而不是ArztFachbereich
对象。
(如果artz
和fachbereich
不是unique_together
,您还需要将distinct()
放在查询末尾,以确保您不会得到重复的@987654340 @ 最终查询集中的实例。)
【讨论】:
似乎工作...但我不明白为什么^^我正在过滤 Arzt 但可以访问特定 ArztFachbereich 对象的 arztfachbereich__note...?以上是关于通过特定的 ManyToMany 对象订购 Django QuerySet的主要内容,如果未能解决你的问题,请参考以下文章
更改模型以添加“通过”关系以订购多对多字段 - Django 1.7 迁移修改
Django 管理界面:使用带中间表的 ManyToMany 字段的 Horizontal_filter