【问题标题】:Django get rid of duplicated queries in nested modelsDjango 摆脱嵌套模型中的重复查询
【发布时间】:2021-10-02 07:33:43
【问题描述】:

我的模型如下图,

class Manufacturer(models.Model):
    name = models.CharField(max_length=100)

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
    name = models.CharField(max_length=300)
    
    @property
    def latest_variant(self):
        return self.carvariant_set.last()

class CarVariant(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE)
    name = models.CharField(max_length=300)

我正在查询所有汽车的最新版本,但我收到了很多重复的查询。 我无法用prefetch_related 消除它

Car.objects.all().prefetch_related('carvariant_set')

如何消除重复查询?

【问题讨论】:

    标签: python django django-models django-queryset django-orm


    【解决方案1】:

    如果您使用.prefetch_related,它将填充carvariant_set 值,但仅适用于.all() 查询,不适用于.last(),这将触发一个新查询。

    我们可以做的是定义如下属性:

    class Car(models.Model):
        manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
        name = models.CharField(max_length=300)
        
        @property
        def latest_variant(self):
            items = getattr(self, '_latest_variants', ())
            if items:
                return items[-1]
            return self.carvariant_set.last()

    然后我们可以通过以下方式预取相关对象:

    from django.db.models import Prefetch
    
    Car.objects.prefetch_related(
        Prefetch(
            'carvariant_set',
            queryset=CarVariant.objects.order_by('pk'),
            to_attr='_latest_variants'
        )
    )

    【讨论】:

      【解决方案2】:

      要删除重复项,请使用“distinct()”。 例如 Car.objects.all().prefetch_related('carvariant_set').distinct()。你可以在这里读到它: https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.distinct

      有时您可能需要告诉“distinct”函数哪些字段使对象不同。默认情况下它是 id,但您可以执行类似“distinct('name')”之类的操作,以避免获得 2 个具有相同名称的实例。

      【讨论】:

      • 不是重复的结果,而是重复的查询。
      猜你喜欢
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 2013-02-18
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多