如何在prefetch_related中排除空的查询集实例?
我有两个模型,分别是 Project
和 Contract
。
它们之间是一对多的关系。
class Contract(models.Model):
project = models.ForeignKey(Project)
我获取了一些 Project
实例,并且这些实例有相关的 Contract
实例。
projects = Project.objects.filter(active=True).prefetch_related(
Prefetch('contract_set', queryset=Contract.objects.filter(**filters), to_attr='contracts')
)
但现在我需要通过把 Contract
的唯一标识符放到 filters
中,来获取与特定 Contract
实例完全匹配的 Project
实例。
filters: Dict = {
'guid': some_guid,
}
但是我得到的却是所有的 Project
实例,其中只有一个实例的 contracts
属性不为空,而其他的 Project
实例的 contracts
属性都是空的。
我发现了一些相关的问题:
如何排除空的预取相关字段的行
在 Django 中过滤空的预取相关字段
但这些对我没有帮助。
我尝试了以下几种方法:
a) 使用 OuterRef
和 Exist
:
projects = Project.objects.filter(**filters_projects).annotate(
has_contracts=Exists(
Contract.objects.filter(project_id=OuterRef('pk'), **filters_contracts)
)
)
projects = projects.filter(has_contracts=True)
b) 使用 annotate
:
projects = (
Project.objects.filter(**filters_projects)
.annotate(num_contracts=Count('contract'))
.exclude(num_contracts=0)
.prefetch_related(
Prefetch('contract_set', queryset=Contract.objects.filter(**filters_contracts), to_attr='contracts')
)
)
这些方法对我都没用...
我该如何实现我想要的功能呢?
1 个回答
2
你需要在 Prefetch
对象和 Project
中都进行筛选,也就是说:
projects = (
Project.objects.filter(
Exists(
Contract.objects.filter(
project_id=OuterRef('pk'), **filters_contracts
)
),
**filters_projects
)
.prefetch_related(
Prefetch(
'contract_set',
queryset=Contract.objects.filter(**filters_contracts),
to_attr='contracts',
)
)
.distinct()
)
所以你要用 **filters_contracts
两次:第一次是为了只获取这些 Project
,第二次是为了处理预先获取的对象。