我正在使用一个包含 ManyToMany
字段 brand_groups
的查询集。用户只能访问基于其组织的 BrandGroups
子集。我试图在仍然使用 values()
的同时保持该 ManyToMany
字段的过滤。 ,它与 View 高度集成。
我正在使用的简化表格:
class BrandGroup(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=256)
organization = models.ForeignKey(
Organization, related_name="brand_groups", null=False
)
class Fact(models.Model):
id = models.CharField(max_length=256, primary_key=True)
brand_groups = models.ManyToManyField(BrandGroup, blank=True)
过去对我有用的是使用 Prefetch
对象来处理这种限制:
qs = Fact.objects.prefetch_related(
Prefetch("brand_groups",
queryset=BrandGroup.objects.filter(
organization_id=self.request.META["ORG_ID_HEADER"]
)))
但我发现 values()
似乎完全忽略了预取。
qs.values("brand_groups__name")
以上内容始终包含完整的关联 BrandGroup
对象(不带过滤器)。
我尝试将 to_attr='org_brand_groups'
添加到 Prefetch
中,但随后 qs.values("org_brand_groups__name")
提示说该字段不存在。
我还尝试使用注释以类似的方式重命名预取字段。我没有收到关于该字段不存在的投诉,但 values()
再次返回未经过滤的查询集。
我成功完成这种过滤的唯一方法是使用子查询:
qs = Fact.objects.annotate(
brand_group_name=Subquery(
BrandGroup.objects.filter(
organization_id=self.request.META["ORG_ID_HEADER"],
Q(id=OuterRef("brand_groups__id"))).values(
"name"[:1],output_field=CharField(),))
# Now it gives me the desired results
qs.values("brand_group_name")
但是这种方法否定了我想要实现的目标。目标是使用联接而不是子查询来提取 BrandGroup
数据。
是否有任何方法可以在不使用 values()
的情况下过滤 ManyToMany
相关字段,而无需子查询?我唯一剩下的想法是在应用 values()
后使用 Python 过滤查询集。
最佳答案
我认为你误解了什么prefetch_related
是:
prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related.
您最好的选择是使用像您的示例中那样的子查询。
关于python - 使用 value() 时过滤 Django 查询集的相关 ManyToMany 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58210744/