通过特定的 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 表上运行(可能JOINed 到ArztFachbereich 表,具体取决于查询)。在这里,filter() 将对应于 SQL WHERE 子句,该子句将行限制为特定值 fachbereich_id,然后 order_bynote 值对剩余的行进行排序。

我认为您的困惑来自于我们正在查询 Artz 模型这一事实。这是否更有意义:ArztFachbereich.objects.filter(fachbereich_id=fb_id).order_by("note")?这两个语句本质上是等价的,但是过滤Artz 让您最终得到Artz 对象而不是ArztFachbereich 对象。

(如果artzfachbereich 不是unique_together,您还需要将distinct() 放在查询末尾,以确保您不会得到重复的@987654340 @ 最终查询集中的实例。)

【讨论】:

似乎工作...但我不明白为什么^^我正在过滤 Arzt 但可以访问特定 ArztFachbereich 对象的 arztfachbereich__note...?

以上是关于通过特定的 ManyToMany 对象订购 Django QuerySet的主要内容,如果未能解决你的问题,请参考以下文章

更改模型以添加“通过”关系以订购多对多字段 - Django 1.7 迁移修改

通过特定的自定义字段订购 WP 查询,不起作用

Django 管理界面:使用带中间表的 ManyToMany 字段的 Horizo​​ntal_filter

在 Django 的 ManyToMany 关系中按 id 添加对象

通过Java中的键编号订购地图对象

Django 模型 ManytoMany getter