select_relate与反向外键 [英] select_related with reverse foreign keys

查看:172
本文介绍了select_relate与反向外键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Django中有两个模型。第一个层级是什么职务(职位)报告哪个职位,第二个是人员和他们所拥有的职位职能。

  class PositionHierarchy(model.Model):
pcn = models.CharField(max_length = 50)
title = models.CharField(max_length = 100)
level = models.CharField max_length = 25)
report_to = models.ForeignKey('PositionHierachy',null = True)


class Person(model.Model):
first_name = models。 CharField(max_length = 50)
last_name = models.CharField(max_length = 50)
...
position = models.ForeignKey(PositionHierarchy)

当我有一个人的记录,我想找到该人的经理,我必须做

  manager = person.position.report_to.person_set.all()[0] 
#不能使用.first(),因为我们还没有升级到1.6 b $ b

如果我得到一个 QuerySet ,我可以使用position和report_to加入(并避免第二次访问数据库),使用 Person.objects.select_related('position','position__reports_to')。filter ...),但是有没有办法避免再次访问数据库以获取person_set?我尝试添加'position__reports_to__person_set'或只是 position__reports_to__person select_related ,但是似乎没有更改查询。这是什么 prefetch_related 是为了?



我想制作一个自定义管理器,以便当我做查询获取人员记录,我也得到他们的PositionHeirarchy和他们的经理人的记录没有更多的往返数据库。这是我到目前为止:

  class PersonWithManagerManager(models.Manager):
def get_query_set(self)
qs = super(PersonWithManagerManager,self).get_query_set()
返回qs.select_related(
'position',
'position__reports_to',
).prefetch_related(


解决方案

是的, c $ c> prefetch_related()是为。它需要一个额外的查询,但想法是它将一次获得所有相关信息,而不是每个 Person



在你的情况下:

  qs.select_related('position__report_to')
.prefetch_related 'position__report_to__person_set')

应该需要两个查询,不管人数在原始查询集中。



将此示例与文档

 >>> ('best_pizza')
.prefetch_related('best_pizza__toppings')


I have two Models in Django. The first has the hierarchy of what job functions (positions) report to which other positions, and the second is people and what job function they hold.

class PositionHierarchy(model.Model):
    pcn = models.CharField(max_length=50)
    title = models.CharField(max_length=100)
    level = models.CharField(max_length=25)
    report_to = models.ForeignKey('PositionHierachy', null=True)


class Person(model.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    ...
    position = models.ForeignKey(PositionHierarchy)

When I have a Person record and I want to find the person's manager, I have to do

manager = person.position.report_to.person_set.all()[0]
# Can't use .first() because we haven't upgraded to 1.6 yet

If I'm getting people with a QuerySet, I can join (and avoid a second trip to the database) with position and report_to using Person.objects.select_related('position', 'position__reports_to').filter(...), but is there any way to avoid making another trip to the database to get the person_set? I tried adding 'position__reports_to__person_set' or just position__reports_to__person to the select_related, but that doesn't seem to change the query. Is this what prefetch_related is for?

I'd like to make a custom manager so that when I do a query to get Person records, I also get their PositionHeirarchy and their manager's Person record without more round trips to the database. This is what I have so far:

class PersonWithManagerManager(models.Manager):
    def get_query_set(self):
        qs = super(PersonWithManagerManager, self).get_query_set()
        return qs.select_related(
            'position',
            'position__reports_to',
        ).prefetch_related(
        )

解决方案

Yes, that is what prefetch_related() is for. It will require an additional query, but the idea is that it will get all of the related information at once, instead of once per Person.

In your case:

qs.select_related('position__report_to')
  .prefetch_related('position__report_to__person_set')

should require two queries, regardless of the number of Persons in the original query set.

Compare this example from the documentation:

>>> Restaurant.objects.select_related('best_pizza')
                      .prefetch_related('best_pizza__toppings')

这篇关于select_relate与反向外键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆