如何在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,第二次是为了处理预先获取的对象。