问题
I have the following serilizers
class AutoSerializer(serializers.ModelSerializer):
class Meta:
model = Auto
fields = ("nombre",)
class MarcaSerializer(WritableNestedModelSerializer):
autos = AutoSerializer(many=True)
class Meta:
model = Marca
fields = ("codigo", "descripcion", "autos")
ModelViewSet
class MarcaViewSet(viewsets.ModelViewSet):
queryset = Marca.objects.all()
serializer_class = MarcaSerializer
def list(self, request, *args, **kwargs):
queryset = self.queryset
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
Querys
How can you optimize access to the base, that is, make fewer inquiries
回答1:
By using a .prefetch_related(..) that fetches the related Auto
instances in one fetch:
class MarcaViewSet(viewsets.ModelViewSet):
queryset = Marca.objects.prefetch_related('autos').all()
serializer_class = MarcaSerializer
def list(self, request, *args, **kwargs):
queryset = self.queryset
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
This will first fetch the Marca
objects, and then look with a JOIN
for all the Auto
objects that are related, and fetch all these objects with a single fetch into memory as well.
So the Auto
objects are loaded in bulk instead of lazily each time fetch the Auto
s for a specific Marca
object.
This kind of optization is documented in the article mentioned by @Jerin Peter George: "Optimizing slow Django REST Framework performance".
This article also discusses how to specify such prefetches at the side of the serializer, such that in case other tasks are done, the prefetch is not done. So we could for example write:
class AutoSerializer(serializers.ModelSerializer):
class Meta:
model = Auto
fields = ("nombre",)
class MarcaSerializer(WritableNestedModelSerializer):
autos = AutoSerializer(many=True)
@classmethod
def setup_eager_loading(cls, queryset):
return queryset.prefetch_related('autos')
class Meta:
model = Marca
fields = ("codigo", "descripcion", "autos")
and then write:
class MarcaViewSet(viewsets.ModelViewSet):
queryset = Marca.objects.all()
serializer_class = MarcaSerializer
def list(self, request, *args, **kwargs):
serializer = self.get_serializer
queryset = serializer.setup_eager_loading(self.queryset)
serializer = serializer(queryset, many=True)
return Response(serializer.data)
来源:https://stackoverflow.com/questions/50950044/how-can-i-optimize-queries-django-rest-framework