How to prefetch a @property with a Django queryset?
Asked Answered
A

1

8

I would like to prefetch a model property to a queryset in Django. Is there a way do that ?

Here are the three models:

class Place(models.Model):
    name = models.CharField(max_length=200, blank=True)
    @property
    def bestpicurl(self):
        try:
            return self.placebestpic.picture.file.url
        except:
            return None

class PlaceBestPic(models.Model):
    place = models.OneToOneField(Place)
    picture = models.ForeignKey(Picture, on_delete=models.CASCADE)

class Picture(models.Model):
    file = ImageField(max_length=500, upload_to="/images/")

I would need something like:

qs = Place.objects.all().select_related('bestpicurl')

Any clue how to do that ? Thanks!

Aerograph answered 17/12, 2017 at 11:28 Comment(0)
F
6

prefetch_related and select_related are instructions that are compiled into the database query/ies. Passing it the name of a pure Python property doesn't work because your database cannot know about them. You would have to select/prefetch the database fields/relations that the property uses under the hood:

qs = Place.objects.select_related('placebestpic')

Now, calling the property will not hit the db:

for p in qs:
    # do stuff with p.bestpicurl

Even though you are following a reverse relation here, you do not use prefetch_related. From the select_related docs:

You can also refer to the reverse direction of a OneToOneField in the list of fields passed to select_related — that is, you can traverse a OneToOneField back to the object on which the field is defined. Instead of specifying the field name, use the related_name for the field on the related object.

Forthwith answered 17/12, 2017 at 11:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.