简体   繁体   中英

How to get all the related fields from a query set in Django?

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?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM