prefetch_related - filter django
prefetch_related para niveles mĂșltiples (2)
Si mis modelos parecen:
class Publisher(models.Model):
pass
class Book(models.Model):
publisher = models.ForeignKey(Publisher)
class Page(models.Model):
book = models.ForeignKey(Book)
y me gustaría obtener el queryset para Publisher que hago Publisher.object.all() . Si luego quiero asegurarme de que prefetch puedo hacer:
Publisher.objects.all().prefetch_related(''book_set'')`
Mis preguntas son:
- ¿Hay alguna manera de realizar esta búsqueda
select_relatedutilizandoselect_relatedo debo usarprefetch_related? - ¿Hay una manera de prefetch el
page_set? Esto no funciona:
Publisher.objects.all().prefetch_related(''book_set'', ''book_set_page_set'')
No, no puede utilizar
select_relatedpara una relación inversa.select_relatedrealiza una unión a SQL, por lo que un solo registro en el conjunto de consultas principal debe hacer referencia a exactamente uno en la tabla relacionada (camposForeignKeyoOneToOne).prefetch_relatedrealidad hace una segunda consulta totalmente separada, almacena en caché los resultados, luego los "une" en el conjunto de consultas en Python. Por lo tanto, es necesario para losManyToManyo InvertirForeignKey.¿Has intentado dos guiones bajos para hacer las gestiones previas de múltiples niveles? Así:
Publisher.objects.all().prefetch_related(''book_set'', ''book_set__page_set'')
Desde Django 1.7, las instancias de la clase django.db.models.Prefetch se pueden usar como un argumento de .prefetch_related . Prefetch constructor de objetos de queryset tiene un argumento queryset que permite especificar los queryset múltiples niveles anidados como ese:
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''
)
)
Se almacena en atributos con el sufijo _list porque uso ListQuerySet para procesar los resultados de búsqueda ListQuerySet (filtro / orden).