【问题标题】:Django fetch related child with parent objectDjango 使用父对象获取相关子对象
【发布时间】:2020-04-14 08:14:39
【问题描述】:

我正在使用 Django 2.2,并且我有一个模型,其中包含两个类 ProductProductRevision。当我检索ProductProducts 列表时,我总是获取相应的ProductRevisionProductRevision 对象递增,只有最后一个修订版应使用 Product 获取。

class Product(models.Model):
    name = models.CharField(max_length=50, null=False, blank=False,
                            verbose_name=_("name"))
    product_code = models.CharField(max_length=10, null=False, blank=False,
                                    verbose_name=_("product code"))
    slug = models.SlugField(null=False, unique=True)

    @property
    def current_item(self):
        return ProductRevision.objects.filter(product=self, active=True).order_by('-version').first()


class ProductRevision(models.Model):
    product = models.ForeignKey(Product, null=True, on_delete=models.PROTECT)
    version = models.IntegerField(default=0,
                                  verbose_name=_("version"))
    active = models.BooleanField(default=False, null=False, blank=True,
                                 verbose_name=_("is active"))
    qty_close = models.IntegerField(default=0,
                                    verbose_name=_("qty of accounts to be closed"))
    price_eur = models.DecimalField(max_digits=6, decimal_places=2, default=0,
                                    verbose_name=_("price in EUR"))

我尝试添加属性current_item 以获取给定产品的最新版本。虽然这是有效的,但效率非常低,因为当我在模板中使用它时,每次显示来自相关 ProductRevision 的字段时,它都会访问数据库。

我根据旧版本的 Django (Fetch latest related objects in django) 找到了这个答案,我想知道当前版本的 Django 是否没有其他方法可以达到相同的结果?我对在我的模型中实现这一点特别感兴趣。

【问题讨论】:

  • 你在使用 postgres 吗?
  • 是的,postgres 11.6

标签: django django-models django-select-related django-related-manager


【解决方案1】:

我已经设法通过使用custom prefetch related queryset 实现了类似的目标

products = Product.objects.prefetch_related(Prefetch(
    'productrevision_set',
    queryset=ProductRevision.objects.order_by('product', '-version').distinct('product'),
    to_attr='latest_revision'
))

上面的查询集每个 Product 只会返回一个 ProductRevision,这实际上在 2 个查询中为所有 Products 提供了最新的 ProductRevision

for product in products:
    for latest_revision in product.latest_revision:
        print(product, latest_revision)

【讨论】:

  • 是的,这就是要走的路!您应该在查询集中将 product 替换为 product_idqueryset=ProductRevision.objects.order_by('product_id', '-version').distinct('product') 否则您会收到 SELECT DISTINCT ON 表达式必须匹配初始 ORDER BY 表达式 错误(请参阅stackoverflow.com/questions/20582966/… 了解更多信息)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 2021-01-25
  • 2013-08-18
  • 2023-03-14
  • 2012-09-16
相关资源
最近更新 更多