python - 使用 value() 时过滤 Django 查询集的相关 ManyToMany 字段

标签 python django

我正在使用一个包含 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/

相关文章:

python - Zsh:未找到 Conda/Pip 安装命令

Python 和封装

django - 将 django 与旧版身份验证 cookie 一起使用

python - 如何检查 tkinter 中的条目是否有一个或多个零

python - 根据多个groupby计算总和

json - 'dict' 对象在 Django Serializer 上没有属性 '_meta'

python - 从 django 中的表中过滤掉空值

django - 如何将 Cache-Control header 添加到托管在 Heroku 上的静态文件中?

linux - Django celery socket.error : [Errno 111] Connection refused

python - 确定德州扑克手牌获胜者的算法