with instalar framework español django django-rest-framework

instalar - Django REST Framework: configuración de la recuperación previa para los serializadores anidados



django rest framework with django 2 (1)

Mi aplicación Django con una API DRF funciona bien, pero he comenzado a tener problemas de rendimiento a medida que la base de datos se llena con los datos reales. Hice algunos perfiles con Django Debug Toolbar y descubrí que muchos de mis endpoints emiten decenas o cientos de consultas en el curso de la devolución de sus datos.

Esperé esto, ya que no había optimizado previamente nada con respecto a las consultas de la base de datos. Ahora que estoy configurando la captación previa, sin embargo, tengo problemas para utilizar los datos del serializador previamente extraído correctamente cuando ese serializador está anidado en un serializador diferente. He estado utilizando esta increíble publicación como una guía sobre cómo pensar sobre las diferentes formas de captación previa.

Actualmente, mi serializador ReadingGroup realiza una ReadingGroup adecuada cuando /api/readinggroups/ endpoint. Mi problema es /api/userbookstats/ endpoint, que devuelve todos los objetos UserBookStats . El serializador relacionado, UserBookStatsSerializer , tiene un ReadingGroupSerializer anidado.

Los modelos, serializadores y conjuntos de vistas son los siguientes:

models.py

class ReadingGroup(models.model): owner = models.ForeignKeyField(settings.AUTH_USER_MODEL) users = models.ManyToManyField(settings.AUTH_USER_MODEL) book_type = models.ForeignKeyField(BookType) .... <other group related fields> def __str__(self): return ''%s group: %s'' % (self.name, self.book_type) class UserBookStats(models.Model): reading_group = models.ForeignKey(ReadingGroup) user = models.ForeignKey(settings.AUTH_USER_MODEL) alias = models.CharField() total_books_read = models.IntegerField(default=0) num_books_owned = models.IntegerField(default=0) fastest_read_time = models.IntegerField(default=0) average_read_time = models.IntegerField(default=0)

serializers.py

class ReadingGroupSerializer(serializers.ModelSerializer): users = UserSerializer(many = True,read_only=True) owner = UserSerializer(read_only=True) class Meta: model = ReadingGroup fields = (''url'', ''id'',''owner'', ''users'') @staticmethod def setup_eager_loading(queryset): #select_related for ''to-one'' relationships queryset = queryset.select_related(''owner'') #prefetch_related for ''to-many'' relationships queryset = queryset.prefetch_related(''users'') return queryset class UserBookStatsSerializer(serializers.HyperlinkedModelSerializer): reading_group = ReadingGroupSerializer() user = UserSerializer() awards = AwardSerializer(source=''award_set'', many=True) class Meta: model = UserBookStats fields = (''url'', ''id'', ''alias'', ''total_books_read'', ''num_books_owned'', ''average_read_time'', ''fastest_read_time'', ''awards'') @staticmethod def setup_eager_loading(queryset): #select_related for ''to-one'' relationships queryset = queryset.select_related(''user'') #prefetch_related for ''to-many'' relationships queryset = queryset.prefetch_related(''awards_set'') #setup prefetching for nested serializers groups = Prefetch(''reading_group'', queryset ReadingGroup.objects.prefetch_related(''userbookstats_set'')) queryset = queryset.prefetch_related(groups) return queryset

views.py

class ReadingGroupViewset(views.ModelViewset): def get_queryset(self): qs = ReadingGroup.objects.all() qs = self.get_serializer_class().setup_eager_loading(qs) return qs class UserBookStatsViewset(views.ModelViewset): def get_queryset(self): qs = UserBookStats.objects.all() qs = self.get_serializer_class().setup_eager_loading(qs) return qs

ReadingGroup la ReadingGroup para el ReadingGroup final de ReadingGroup (en realidad ReadingGroup sobre la eliminación de consultas duplicadas para ese punto final aquí ), y ahora estoy trabajando en el UserBookStats final UserBookStats .

El problema que estoy teniendo es que, con mi setup_eager_loading actual en el UserBookStatsSerializer , no parece utilizar la configuración de captación previa por el método de carga ansioso en ReadingGroupSerializer . Todavía estoy un poco confuso con la sintaxis del objeto Prefetch . Me inspiré en esta excelente respuesta para probar ese enfoque.

Obviamente, el método get_queryset de UserBookStatsViewset no llama a setup_eager_loading para los objetos ReadingGroup , pero estoy seguro de que hay una manera de lograr la misma setup_eager_loading ReadingGroup .


prefetch_related() admite la captación previa de relaciones internas mediante el uso de la sintaxis de subrayado doble:

queryset = queryset.prefetch_related(''reading_group'', ''reading_group__users'', ''reading_group__owner'')

No creo que Django REST proporcione soluciones elegantes listas para usar para buscar todos los campos necesarios automáticamente.