Django get rid of duplicated queries in nested models

Viewed 96

I have models as shown below,

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)

and I am making a query to get the latest variant of all cars, I am getting much duplicated queries. I couldn't eliminate it with prefetch_related

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

How can I eliminate the duplicated queries?

2 Answers

If you use .prefetch_related it will populate the carvariant_set value, but only for a .all() query, not for a .last(), that will trigger a new query.

What we can do is define a property like:

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()

Then we can prefetch the related object with:

from django.db.models import Prefetch

Car.objects.prefetch_related(
    Prefetch(
        'carvariant_set',
        queryset=CarVariant.objects.order_by('pk'),
        to_attr='_latest_variants'
    )
)
Related