【问题标题】:select_related with reverse foreign keysselect_related 与反向外键
【发布时间】:2014-06-01 01:24:03
【问题描述】:

我在 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]
# Can't use .first() because we haven't upgraded to 1.6 yet

如果我让人们使用QuerySet,我可以使用Person.objects.select_related('position', 'position__reports_to').filter(...) 与 position 和 report_to 一起加入(并避免第二次访问数据库),但是有什么方法可以避免再次访问数据库得到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()
        return qs.select_related(
            'position',
            'position__reports_to',
        ).prefetch_related(
        )

【问题讨论】:

  • 可能是错字,但应该是get_queryset(),而不是get_query_set
  • @Paolo 在 Django 1.5 中是 get_query_set

标签: django django-models django-queryset django-1.5 django-managers


【解决方案1】:

是的,这就是prefetch_related() 的用途。这将需要一个额外的查询,但想法是它会一次获取所有相关信息,而不是每个Person 一次。

在你的情况下:

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

应该需要两个查询,无论原始查询集中Persons 的数量是多少。

比较documentation中的这个例子:

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

【讨论】:

    猜你喜欢
    • 2011-02-27
    • 2011-12-27
    • 2016-10-05
    • 1970-01-01
    • 2018-10-16
    • 2013-01-01
    • 2019-02-23
    • 2019-12-01
    • 2019-02-11
    相关资源
    最近更新 更多