【问题标题】:Django prefetch table that is not directly related不直接相关的 Django 预取表
【发布时间】:2019-12-09 11:11:40
【问题描述】:

使用以下模型是否可以获取Category 对象并预取OrderLine 以便category.orderlines.all() 可以访问它?

class Category(models.Model):
    name = models.CharField(...)

class Product(models.Model):
    category = models.ForeignKey(Category, related_name='products', ...)
    name = models.CharField(...)
    price = models.DecimalField(...)

class OrderLine(models.Model):
    product = models.ForeignKey(Product, related_name='orderlines', ...)

我知道您可以通过产品进行嵌套预取,但我想直接从 Category 访问 OrderLine 对象,而不是通过 Product

from django.db.models import Prefetch

categories = Category.objects.prefetch_related(Prefetch(
    'products__orderlines',
    queryset=OrderLine.objects.filter(...)
))

for category in categories:
    for product in category.products.all():
        for line in product.orderlines.all():
            ...

所需用途:

for category in categories:
    for line in category.orderlines.all():
        ...

更新

添加to_attr='orderlines' 会导致:

ValueError: to_attr=orderlines 与 Product 模型上的字段冲突。

更改属性名称to_attr='lines' 不会导致错误,但不会将属性添加到Category 对象中。它预取Product,然后为每个产品添加一个lines 属性。

【问题讨论】:

  • @sdementen 这些也是嵌套预取,但我的问题是关于绕过嵌套预取的第一级并将第二级作为属性添加到主查询集中的每个对象。从我目前所看到的情况来看,我认为它至少会涉及一个自定义 Prefetch 函数,并且可能会使用一个自定义查询集方法来代替 prefetch_related
  • 对不起@bdoubleu,实际上您描述的行为与其他两篇文章中的行为相同。

标签: django


【解决方案1】:

我最接近的方法是使用ArraySubquery。唯一的缺点是 lines 是字典列表而不是模型实例。

Category.objects.annotate(
    lines=ArraySubquery(
        OrderLine.objects
        .filter(category=OuterRef('id'))
        .values(json=JSONObject(
            id='id',
            product_name='product__name',
            quantity='quantity',
        ))
    )
)

【讨论】:

    猜你喜欢
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2012-09-10
    • 2018-11-11
    • 2020-05-09
    • 2020-05-21
    • 2015-12-22
    相关资源
    最近更新 更多