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!
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.
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 .
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With