53

Django には 2 つのモデルがあります。1 つ目は、どの職務 (役職) が他のどの役職に報告するかという階層を持ち、2 つ目は、従業員とその役職です。

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)

Person レコードがあり、その人の上司を見つけたい場合は、次のようにする必要があります。

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

で人を取得している場合QuerySet、 を使用して position と report_to に参加できます (データベースへの 2 回目のトリップを回避できます)Person.objects.select_related('position', 'position__reports_to').filter(...)が、person_set を取得するためにデータベースへの別のトリップを回避する方法はありますか? 'position__reports_to__person_set'にorを追加しようとしposition__reports_to__personましたselect_relatedが、クエリは変更されないようです。これは何prefetch_relatedのためですか?

Person レコードを取得するためのクエリを実行するときに、データベースへの往復を行わずに、PositionHeirarchy とそのマネージャーの Person レコードも取得できるように、カスタム マネージャーを作成したいと考えています。これは私がこれまでに持っているものです:

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(
        )
4

1 に答える 1

41

はい、それがprefetch_related()目的です。追加のクエリが必要になりますが、アイデアは、関連するすべての情報を一度に取得するのではなく、一度に取得することPersonです。

あなたの場合:

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

Persons元のクエリ セットの数に関係なく、2 つのクエリが必要です。

ドキュメントのこの例を比較してください:

>>> Restaurant.objects.select_related('best_pizza')
                      .prefetch_related('best_pizza__toppings')
于 2014-04-16T23:22:56.727 に答える