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)
@property
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 = userprofile.order_history.all()
is equivalent to
user_order=UserProfile.objects.prefetch_related('order_history').get(slug=self.slug)
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=UserProfile.objects.prefetch_related('order_history').get(slug=self.slug)
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.