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_related
utilizandoselect_related
o 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_related
para una relación inversa.select_related
realiza 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 (camposForeignKey
oOneToOne
).prefetch_related
realidad 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 losManyToMany
o 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).