Reputation: 85
I want to get all objects from a User model with single queryset, but I have no idea on how to do it.
I got a 2 relationship model to user model, I can get the objects with these code below
User.objects.get(id=1).profile
User.objects.get(id=1).groups
But how can i get all objects of user with single queryset only?
Upvotes: 6
Views: 14915
Reputation: 525
You can access the data of ManyToMany, Foreign field data in queryset with below format double underscore.
columnname.referred.table__reference_column
class DigitalApplicationsAndPlatform(models.Model):
digital_area = models.ForeignKey(
MasterDigitalProductsAreas, on_delete=models.CASCADE
)
keywords = models.ManyToManyField(
"MasterKeyword", blank=True, related_name="digital_keyword"
)
Queryset:
m = models.DigitalApplicationsAndPlatform.objects.filter(id=1).values(
"digital_product", "digital_area__digital_area", "keywords__keyword"
)
Above queryset will have multiple values of digital_product, digital_area__digital_area, since keywords field has ManyToMany relationship.
Result:
<QuerySet [{'digital_product': '10,000ft Insights',
'digital_area__digital_area': 'Productivity & Collaboration',
'keywords__keyword': '_10000ft Insights_'}, {'digital_product': '10,000ft
Insights', 'digital_area__digital_area': 'Productivity & Collaboration',
'keywords__keyword': '_10K Insights_'}, {'digital_product': '10,000ft
Insights', 'digital_area__digital_area': 'Productivity & Collaboration',
'keywords__keyword': '_10,000ft Insights_'}, {'digital_product': '10,000ft
Insights', 'digital_area__digital_area': 'Productivity & Collaboration',
'keywords__keyword': "_10K' Insights_"}]>
Above query have performance implication. Django hits database everytime you try to access related model data.
m = (
models.DigitalApplicationsAndPlatform.objects.filter(id=1)
.select_related("digital_area")
.prefetch_related("keywords")
.values("digital_product", "digital_area__digital_area", "keywords__keyword")
)
You have use below hints to tackle it with above queryset.
select_related
- for Foreign key and OneToOne field.prefetch_related
- For ManyToMany and Reverse lookupBelow official document will give some idea about accessing related data.
https://docs.djangoproject.com/en/2.2/topics/db/queries/#lookups-that-span-relationships
Upvotes: 1
Reputation: 20702
Use select_related
and prefetch_related
, as described here:
user = User.objects.select_related('profile').prefetch_related('groups').get(id=1)
user.profile # does not query the database again
user.groups # does not query the database again
Note however that since user
<-> groups
is a m2m relationship, this will hit the database twice in any case. If you're only fetching one specific user, adding the prefetch_related
doesn't really make a difference. It does make a difference if you loop through a list of users, since only one query is required to fetch all m2m related groups, instead of one query for each user:
users = User.objects.select_related('profile').prefetch_related('groups')\
.filter(is_staff=True)
for user in users: # 2 queries
print(user.profile)
for group in user.groups: # no database query
print(group.name)
Upvotes: 5