【问题标题】:How to get all the related fields from a query set in Django?如何从 Django 中的查询集中获取所有相关字段?
【发布时间】:2018-12-17 17:21:19
【问题描述】:

我有两个模型,SessionSessionType,它们具有多对一的关系。在Session 上还有一个Family 外键,像这样:

from django.db import models


class SesssionType(models.Model):
    pass


class Session(models.Model):
    session_type = models.ForeignKey('SessionType')
    family = models.ForeignKey('Family')

对于Family 的某个实例family,我在session_set 中有几个Session 对象:

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>]>

我想获得一个包含这些SessionTypes 的SessionTypes 的查询集,类似于以下列表:

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>]

select_related 方法似乎是为此而生的,但调用它并不会产生预期的结果:

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>]>

如上所示,对select_related() 的调用产生了一个带有Session 对象的查询集,而不是SessionType 对象。如何获取SessionType 对象?

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    执行查询以获取一个家庭的所有会话,但只要求返回“session_type”值而不是每个会话的所有数据。

    一旦您只返回了 session_types,您就可以使用 distinct() 将该响应归结为唯一值列表。

    
    family.session_set.all().values('session_type').distinct()
    
    

    【讨论】:

      【解决方案2】:

      正如您所说,您可以使用新查询集来选择所有 SessionType 对象。

      select_related 用法不同

      根据 Django 文档和我使用的所有 select_related 不更改查询集对象类型。但只能通过一次查询从数据库中选择所有相关对象。例如看这个查询:

      for item in family.session_set.select_related('session_type').all():
           print item.session_type
      

      访问数据库一次,但是当你写这个时:

      for item in family.session_set.all():
           print item.session_type
      

      对于每次打印,发生一次数据库命中,并且发生一次基本查询的数据库命中。它对于小数据并不重要,但是当您的数据太大时,如果没有 select_related,您的网站就会变慢。但要注意使用它。如果您使用过多,则相反,您的网站会变慢。

      https://docs.djangoproject.com/en/2.0/ref/models/querysets/#select-related上查看更多信息

      【讨论】:

        【解决方案3】:

        我通过过滤所有 SessionType 对象来解决这个问题,如下所示:

        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>]>
        

        但是,我有一种暗示,这比仅从 family.session_set 中的 Session 对象中获取相应的 session_type 效率低,因此解释为什么 select_related() 无法按预期工作仍然是最重要的欢迎。

        【讨论】:

          猜你喜欢
          • 2020-03-05
          • 2013-03-20
          • 2016-07-11
          • 1970-01-01
          • 1970-01-01
          • 2016-09-05
          • 2012-02-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多