prefetch_related for multiple Levels

前端 未结 2 1939
长情又很酷
长情又很酷 2020-12-08 03:56

If my Models look like:

class Publisher(models.Model):
    pass

class Book(models.Model):
    publisher = models.ForeignKey(Publisher)

class Page(models.Mo         


        
相关标签:
2条回答
  • 2020-12-08 04:38

    Since Django 1.7, instances of django.db.models.Prefetch class can be used as an argument of .prefetch_related. Prefetch object constructor has a queryset argument that allows to specify nested multiple levels prefetches like that:

    Project.objects.filter(
            is_main_section=True
        ).select_related(
            'project_group'
        ).prefetch_related(
            Prefetch(
                'project_group__project_set',
                queryset=Project.objects.prefetch_related(
                    Prefetch(
                        'projectmember_set',
                        to_attr='projectmember_list'
                    )
                ),
                to_attr='project_list'
            )
        )
    

    It is stored into attributes with _list suffix because I use ListQuerySet to process prefetch results (filter / order).

    0 讨论(0)
  • 2020-12-08 05:00
    1. No, you cannot use select_related for a reverse relation. select_related does a SQL join, so a single record in the main queryset needs to reference exactly one in the related table (ForeignKey or OneToOne fields). prefetch_related actually does a totally separate second query, caches the results, then "joins" it into the queryset in python. So it is needed for ManyToMany or reverse ForeignKey fields.

    2. Have you tried two underscores to do the multi level prefetches? Like this: Publisher.objects.all().prefetch_related('book_set', 'book_set__page_set')

    0 讨论(0)
提交回复
热议问题