子查询:否定外部参照不起作用

时间:2018-06-15 07:40:58

标签: python django subquery

我有三个模型项目,简介和公司: (使用django 2.0和python 3.5)

class Company:
     pass
class Profile:
     company = models.ForeignKey(Company, on_delete=models.CASCADE)
class Project:
     companies = models.ManyToManyRelatedField(Company, related_name="projects")
     profiles = models.ManyToManyRelatedField(Profile, related_name="projects")

隐含的限制是,当将配置文件分配给项目时,也必须将其公司分配给该项目。

但是,并不总是满足这种限制,所以我想找出哪些对象不符合它。

如果我尝试使用Exists()子查询找到所有具有此类无效作业的项目:

    qs = Project.objects.annotate(x=Exists(
        Profile.objects.filter(
            # find all profiles assigned to project
            projects=OuterRef('pk')
        ).exclude(
            # exclude profiles where company is assigned to project
            company__projects=OuterRef('pk')
        )
    )).filter(x=True)

尝试评估qs会导致:

 ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.

如果我将exclude替换为filter,它会再次起作用;同样,使用Q()表达式时,只有在company__projects__in=OuterRef('pk')被否定时,查询集才会失败。

这是OuterRef的限制吗?文档没有提到类似的内容,我也找不到错误报告。

修改

我确实找到了使用第二个子查询的解决方法:

    qs = Project.objects.annotate(x=Exists(
        Profile.objects.filter(
            # find all profiles assigned to project
            projects=OuterRef('pk')
        ).exclude(
            # exclude profiles where company is assigned to project
            id__in=Subquery(Profile.objects.filter(
                company__projects=OuterRef(OuterRef('pk'))
            ).values('id'))
        )
    )).filter(x=True)

然而,这在我看来是次优的并且降低了代码的可读性,所以我的原始问题仍然存在。

0 个答案:

没有答案