Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prefetch a @property with a Django queryset?

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!

like image 611
Paul Noon Avatar asked Dec 17 '17 11:12

Paul Noon


People also ask

How does Django prefetch work?

Django's prefetch_related() method reduces the number of queries made to your database by combining all related model lookups into one additional query. In the professionals list example, we can use prefetch_related() to get the professionals and their related work experiences and references in 3 queries instead of 21.

How does QuerySet work in Django?

A QuerySet represents a collection of objects from your database. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. In SQL terms, a QuerySet equates to a SELECT statement, and a filter is a limiting clause such as WHERE or LIMIT .

What does QuerySet []> mean?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data.

How does prefetch related work?

prefetch_related does a separate lookup for each relationship, and performs the “joining” in Python. It is different from select_related , the prefetch_related made the JOIN using Python rather than in the database. Let's dig into it with an example. We have 10 stores in the database and each store has 10 books.


1 Answers

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.

like image 171
user2390182 Avatar answered Sep 22 '22 12:09

user2390182