Learner Learner - 2 months ago 13
Python Question

Could not figure out the use of prefetch_related in django

There is a scenario where i want to show total purchase of the user. I did using @property inside models of userprofiles. Fortunately, it is working as i expected. But i want to use prefetch_related for optimizing django queries as total purchase of user is calculated from order_history which has ManyToMany Relation with the OrderMenu.

How i did ?

class UserProfile(models.Model):
user = models.OneToOneField(User)
slug = models.SlugField(unique=True,blank=True,null=True)
restaurant = models.ManyToManyField(Restaurant, blank=True)
order_history = models.ManyToManyField(OrderMenu, blank=True)
# favorites = models.ManyToManyField(Restaurant)
is_owner = models.BooleanField(default=False)

def total_purchase(self):
total_purchase = 0
# user_order = UserProfile.objects.prefetch_related('order_history').get(slug=self.slug)
userprofile = UserProfile.objects.get(slug=self.slug)
user_order = userprofile.order_history.all()
for usr in user_order:
total_purchase += usr.get_cost()
return total_purchase

In this solution, isn't

userprofile = UserProfile.objects.get(slug=self.slug) user_order =

is equivalent to


I am so much confused with prefetch_related. Could anyone please enlighten me with simple language? Sorry i am non-native English speaker.


The difference between the two is

In case of

userprofile = UserProfile.objects.get(slug=self.slug) #hits database

This query gets the object of userprofile based on condition from database

user_order = userprofile.order_history.all() #hits database again

This query gets user_order queryset using userprofile object hitting database again.

i.e. userprofile hits database as well as user_order

In this case however


user_order queryset set returns not only user profile object but also 'order_history' queryset that is related to UserProfile object in one hit to database. Now when you access 'order_history' querset with user_order object it will not hit database, but gets the queryset of 'order_history' from prefetched QuerySet cache of 'user_order'. more about it here.