Reputation: 57761
I have two models, Session
and SessionType
which have a many-to-one relationship. There is also a Family
foreign key on Session
, like so:
from django.db import models
class SesssionType(models.Model):
pass
class Session(models.Model):
session_type = models.ForeignKey('SessionType')
family = models.ForeignKey('Family')
For a certain instance family
of Family
, I have several Session
objects in the session_set
:
ipdb> family.session_set.all()
<QuerySet [<Session: Welcome>, <Session: Breastfeeding Preparation - Timothy Anderson>, <Session: First-Time Parents: The Basics of Birth>, <Session: Initial Postpartum Lactation>, <Session: Sleep Techniques for New Babies>, <Session: Breastfeeding Preparation>, <Session: Newborn Care Basics>, <Session: Easing the Transition Back to Work>, <Session: Preparing for Parenting>, <Session: Decoding Baby Cues>, <Session: Postpartum Doula Support>, <Session: First-Time Parents: Birth Prep Q&A>, <Session: Postpartum Lactation Follow-Up>, <Session: Sleep Training for 4 Months & Beyond>, <Session: Mental Wellness in Pregnancy>, <Session: Infant CPR>, <Session: Prenatal Pelvic Physical Therapy>, <Session: Prenatal Massage>]>
I would like to get a queryset containing the SessionType
s of these Session
s, similar to the following list:
ipdb> [session.session_type for session in family.session_set.all()]
[<SessionType: Welcome>, <SessionType: Breastfeeding Preparation>, <SessionType: First-Time Parents: The Basics of Birth>, <SessionType: Initial Postpartum Lactation>, <SessionType: Sleep Techniques for New Babies>, <SessionType: Breastfeeding Preparation>, <SessionType: Newborn Care Basics>, <SessionType: Easing the Transition Back to Work>, <SessionType: Preparing for Parenting>, <SessionType: Decoding Baby Cues>, <SessionType: Postpartum Doula Support>, <SessionType: First-Time Parents: Birth Prep Q&A>, <SessionType: Postpartum Lactation Follow-Up>, <SessionType: Sleep Training for 4 Months & Beyond>, <SessionType: Mental Wellness in Pregnancy>, <SessionType: Infant CPR>, <SessionType: Prenatal Pelvic Physical Therapy>, <SessionType: Prenatal Massage>]
It seems like the select_related
method is meant for this, but calling it doesn't produce the desired result:
ipdb> family.session_set.select_related('session_type')
<QuerySet [<Session: Welcome>, <Session: Breastfeeding Preparation - Timothy Anderson>, <Session: First-Time Parents: The Basics of Birth>, <Session: Initial Postpartum Lactation>, <Session: Sleep Techniques for New Babies>, <Session: Breastfeeding Preparation>, <Session: Newborn Care Basics>, <Session: Easing the Transition Back to Work>, <Session: Preparing for Parenting>, <Session: Decoding Baby Cues>, <Session: Postpartum Doula Support>, <Session: First-Time Parents: Birth Prep Q&A>, <Session: Postpartum Lactation Follow-Up>, <Session: Sleep Training for 4 Months & Beyond>, <Session: Mental Wellness in Pregnancy>, <Session: Infant CPR>, <Session: Prenatal Pelvic Physical Therapy>, <Session: Prenatal Massage>]>
As seen above, the call to select_related()
produced a query set with Session
objects, and not SessionType
objects. How can I get the SessionType
objects?
Upvotes: 2
Views: 7595
Reputation: 343
Do the query to get all the sessions for a family but only ask for the 'session_type' value to be returned rather than all the data for each session.
Once you have only the session_types returned, you can then use distinct() to get that response boiled down to only a list of the unique values.
family.session_set.all().values('session_type').distinct()
Upvotes: 1
Reputation: 1950
as you say you can use new query set to select all SessionType
objects.
but select_related
usage is different
according to Django documentation and all I used select_related not change queryset object type. but only select all related objects from database by one query. for example see this query:
for item in family.session_set.select_related('session_type').all():
print item.session_type
hits database once but when you write this:
for item in family.session_set.all():
print item.session_type
for every print one database hit occurred and one database hit for base query occurred. its not important for little data but when your data is too large your site went slow without select_related. but be aware of using it. if you use it too much the action is opposite and your site went slow.
see more on https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-related
Upvotes: 1
Reputation: 57761
I worked around this problem by filtering all SessionType
objects, like so:
ipdb> SessionType.objects.filter(session__family=family).order_by('session__session_number')
<QuerySet [<SessionType: Welcome>, <SessionType: First-Time Parents: The Basics of Birth>, <SessionType: Initial Postpartum Lactation>, <SessionType: Sleep Techniques for New Babies>, <SessionType: Breastfeeding Preparation>, <SessionType: Newborn Care Basics>, <SessionType: Easing the Transition Back to Work>, <SessionType: Preparing for Parenting>, <SessionType: Decoding Baby Cues>, <SessionType: Postpartum Doula Support>, <SessionType: First-Time Parents: Birth Prep Q&A>, <SessionType: Postpartum Lactation Follow-Up>, <SessionType: Sleep Training for 4 Months & Beyond>, <SessionType: Mental Wellness in Pregnancy>, <SessionType: Infant CPR>, <SessionType: Prenatal Pelvic Physical Therapy>, <SessionType: Prenatal Massage>]>
However, I have an inkling that this is less efficient than just getting the corresponding session_type
from the Session
objects in the family.session_set
, so explanations as to why select_related()
is not working as expected are still most welcome.
Upvotes: 1