django ORM - 在 M2M 上排除 F 功能不起作用

Posted

技术标签:

【中文标题】django ORM - 在 M2M 上排除 F 功能不起作用【英文标题】:django ORM - Exclude on M2M with F-function not working 【发布时间】:2020-07-06 03:11:04 【问题描述】:

我有以下型号:

class Activity(models.Model):
   user = models.ForeignKey(User, related_name='activities')
   project = models.ForeignKey(Project, related_name='activities')


class Project(models.Model):
   assignees = models.ManyToManyField(User, related_name='projects')

现在我想查询属于不在项目受让人中的用户的所有活动。

我的查询:

Activity.objects.exclude(project__assignees=F('user'))

问题是,我总是收到这个错误:

django.db.utils.OperationalError: (1054, "Unknown column 'U2.id' in 'on clause'")

我正在开发 django 2.2.11 和 mysql

我找到了几个old django bugs,但它们应该早就被修复了。

有什么想法可以解决我的问题吗?我的活动表很大,我需要一种有效的方法。我很乐意不使用原始查询。

谢谢!

【问题讨论】:

当我检查查询时,看起来它根本没有定义 U2 表。但是我猜你可以用一个子查询来解决这个问题。 【参考方案1】:

看起来这是一个错误,因为在生成的查询中,U2 表甚至没有定义。您可能需要提交ticket at Django's ticketing system。

但是,您可以通过注释然后过滤来解决问题:

from django.db.models import Exists, OuterRef

Activity.objects.annotate(
    valid=~Exists(Project.objects.filter(
        activities=OuterRef('pk'),
        assignees=OuterRef('user')
    ))
).filter(valid=True)

或从django-3.0 开始,您可以直接在Exists 上过滤:

from django.db.models import Exists, OuterRef

Activity.objects.filter(
    ~Exists(Project.objects.filter(
        activities=OuterRef('pk'),
        assignees=OuterRef('user')
    ))
)

【讨论】:

太棒了!永远找不到这个解决方案! 创建票证:code.djangoproject.com/ticket/31401#ticket

以上是关于django ORM - 在 M2M 上排除 F 功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

这在 Django ORM 中真的不可能吗?

如果找到湮灭对,Django ORM 排除结果

Django ORM相关

Django 迁移错误:您无法更改 M2M 字段或从 M2M 字段更改,或通过 = 在 M2M 字段上添加或删除

Django ORM。如何排除旧数据?

带有排除的 Django ORM 查询无法正常工作