【问题标题】:Prefech many to many relation for one class instance为一个类实例预取多对多关系
【发布时间】:2020-07-27 13:09:19
【问题描述】:

我想限制详细视图的查询。我想在较少的查询中访问一个类实例的多个多对多字段。似乎 prefetch_related 不适用于 get 并且服务器会针对每个多对多字段访问他的数据库。

JobInstance = Job.objects.get(pk=id).prefetch_related('cities').prefetch_related('experience_level')

【问题讨论】:

    标签: python django django-views django-orm


    【解决方案1】:

    可以让它工作,通过重新排序,比如:

    job_instance = Job.objects<b>.prefetch_related('cities', 'experience_level')</b>.get(pk=id)

    .prefetch_related(..) 是在 QuerySet 上定义的,当您执行 .get(..) 时,您将获取对象,并且您不再使用查询集。

    但对于单个对象,.prefetch_related(..)不会提高效率。毕竟.prefetch_related(..) 会在这里做两个额外的查询来获取相关对象,和不预取一样多,然后评估job_instance 的相关对象。

    因此,

    .prefetch_related(..) 在您想要批量获取多个 对象的相关对象时很有用。

    【讨论】:

    • 当使用 prefetch_related 时,它实际上会再次访问数据库。最好调用返回数据的类实例的函数。
    • @csandreas1: prefetch_relatedjob_instance.cities.all() (没有这样的预取)都会导致额外的查询,因此,正如所说的你没有“获得”。 .select_related(..) 将“搭载”查询以获取对象,但您不能将其用于一对多关系或多对多关系,因为这可能会产生大量重复记录。
    • 其实有收获!当多次使用带有关联数据的模板标签时,我没有点击数据库
    • @csandreas1:好吧,如果您将job_instance.cities.all() 存储在某个地方,它也不会再次访问数据库。它产生多次命中的原因是,如果你定义 job_instance.cities.all(),你会复制旧的查询集,而没有它的缓存行为。
    猜你喜欢
    • 2017-09-11
    • 2021-11-06
    • 2017-07-18
    • 2020-07-10
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    相关资源
    最近更新 更多