Django 摆脱嵌套模型中的重复查询
Django get rid of duplicated queries in nested models
我有如下图的模型,
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')
如何消除重复查询?
如果您使用 .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):
<strong>items</strong> = getattr(self, '_latest_variants', ())
if items:
return <strong>items[-1]</strong>
return self.carvariant_set.last()
然后我们可以预取相关对象:
from django.db.models import <strong>Prefetch</strong>
Car.objects.prefetch_related(
<strong>Prefetch(</strong>
'carvariant_set',
queryset=CarVariant.objects.order_by('pk'),
to_attr='_latest_variants'
<strong>)</strong>
)
要删除重复项,您可以使用“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 个具有相同名称的实例。
我有如下图的模型,
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')
如何消除重复查询?
如果您使用 .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):
<strong>items</strong> = getattr(self, '_latest_variants', ())
if items:
return <strong>items[-1]</strong>
return self.carvariant_set.last()
然后我们可以预取相关对象:
from django.db.models import <strong>Prefetch</strong>
Car.objects.prefetch_related(
<strong>Prefetch(</strong>
'carvariant_set',
queryset=CarVariant.objects.order_by('pk'),
to_attr='_latest_variants'
<strong>)</strong>
)
要删除重复项,您可以使用“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 个具有相同名称的实例。