我有三个模型项目,简介和公司: (使用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)
然而,这在我看来是次优的并且降低了代码的可读性,所以我的原始问题仍然存在。