通过 m2m 关系的直通表的值过滤 django 查询集

Posted

技术标签:

【中文标题】通过 m2m 关系的直通表的值过滤 django 查询集【英文标题】:Filtering django queryset by a value of the through table of a m2m relationship 【发布时间】:2020-04-13 04:16:09 【问题描述】:

我正在尝试这样做: queryset.filter(m2m_related_lookup__through_table_field=value)

这些是简化的模型:

class User(models.Model):
    name = models.CharField("nom", max_length=100)
    surname = models.CharField("cognoms", max_length=100)

class Activity(models.Model):
    name = models.CharField("Títol", max_length=200)
    date_start = models.DateField("Dia inici")
    date_end = models.DateField("Dia finalització")
    enrolled = models.ManyToManyField(User, related_name='enrolled_activities', through='ActivityEnrolled')

class ActivityEnrolled(models.Model):
    class Meta:
        db_table = 'main_activity_personetes_enrolled'

    activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
    user = models.ForeignKey(Personeta, on_delete=models.CASCADE)
    date_enrolled = models.DateTimeField("data d'inscripció")
    confirmed = models.BooleanField("confirmada", default=False)

我想这很简单,只有 2 多个带有自定义直通表,所以我可以在那里存储注册日期和其他一些东西。 此关系在 Activity 中设置,related_name 为“enrolled_activities”。

那么,如何使用 Django 的 ORM 查询“2019 年 ActivityEnrolled.enrollment_date 所在的所有用户”?

这是用于 Django Admin 中的 change_list 视图的自定义过滤器(使用 admin.SimpleListFilter),它列出了用户项。换句话说,就像我在做 User.objects.filter(blabla)。

尝试:queryset.filter(enrolled_activities__date_enrolled__year=2019) 显然会抛出错误Related Field got invalid lookup: date_enrolled,因为 enrolled_activities 不是指直通表而是指相关表(即:Activity),且该字段不存在。

是查询直通表而不是用户的唯一解决方案吗? 比如:ActivityEnrolled.objects.filter(date_enrolled__year=2019) + 对结果进行分组,因此每个用户只返回一行。我知道我可以这样做,但这很讨厌,我一直在尝试找到一种更清洁的方法来避免它,但没有成功。

非常感谢!!

【问题讨论】:

【参考方案1】:

那么,如何使用Django的ORM查询“2019年ActivityEnrolled.enrollment_date所在的所有用户”?

多对多关系实际上只是两个一对多表的组合。因此,我们可以过滤一对多关系:

User.objects.filter(<b>activityenrolled__enrollment_date__year=2019</b>)<b>.distinct()</b>

.distinct() 将防止产生同一用户,如果该用户在 2019 年注册了多个活动。

【讨论】:

完美答案,非常感谢!这很愚蠢,但我不知道您可以在过滤时通过像这样将模型名称小写来引用表格。

以上是关于通过 m2m 关系的直通表的值过滤 django 查询集的主要内容,如果未能解决你的问题,请参考以下文章

Django:通过添加 m2m 导致“当前事务被中止,命令被忽略,直到事务块结束”

在 Django 中过滤第二级多对多关系

在 django 中使用过滤器遍历 m2m

具有多对多和直通表的 Graphene-django

在 M2M 字段 Django 中过滤标签

Unhashable 类型:尝试在 Django 中使用 post_save 动态添加 m2m 关系时出现“列表”错误