Ich benutze die folgenden Reihe von Serialisierer zu erreichen, eine Join, die gut auf meine Entwicklung Setup funktionieren, führt aber schrecklich, wenn es einen Abstand zwischen dem Website-Server und dem Datenbankserver gibt. Ich wurde misstrauisch gegenüber dem SQL, das die Show ausführt, und habe etwas Logging gemacht; es scheint, dass es für jeden Eintrag eine neue Abfrage erstellt und die Ergebnisse kombiniert, anstatt den gesamten Join auf einmal durchzuführen und den Join wie gewünscht zurückzuschicken. Hier sind meine Serializer:Effiziente Join mit Django REST Framework Serialisierer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
exclude = ('password', 'last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined',
'groups', 'user_permissions')
class DepartmentSerializer(serializers.HyperlinkedModelSerializer):
curator = UserSerializer()
class Meta:
model = Department
fields = '__all__'
class CategorySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Category
fields = '__all__'
class DetailedLinkedContentSerializer(serializers.HyperlinkedModelSerializer):
category = CategorySerializer()
department = DepartmentSerializer()
type = serializers.SerializerMethodField()
class Meta:
fields = '__all__'
model = LinkedContent
def get_type(self, obj):
return 'link'
class DetailedFileContentSerializer(serializers.HyperlinkedModelSerializer):
category = CategorySerializer()
department = DepartmentSerializer()
link_url = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
class Meta:
fields = '__all__'
model = FileContent
def get_link_url(self, obj):
return obj.file.url
def get_type(self, obj):
return obj.file_type
Wie Sie sehen können, ich tue meine ‚nachziehen‘ von Feldern in einem Serializer als Serializer anderer Modelle einschließlich, wie Kategorie = CategorySerializer(). Es sieht so aus, als ob DRF recommends, wenn ich etwas nicht falsch verstehe. Hier ist eine kleine Auswahl der Hunderte von Anfragen auf meiner Entwicklungsumgebung wird ausgeführt:
(0.001) SELECT "content_linkedcontent"."id", "content_linkedcontent"."link_text", "content_linkedcontent"."department_id", "content_linkedcontent"."category_id", "content_linkedcontent"."visibility_rank", "content_linkedcontent"."link_url" FROM "content_linkedcontent"; args=()
(0.001) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,)
(0.001) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 24; args=(24,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3; args=(3,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 29; args=(29,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 4; args=(4,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 25; args=(25,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 29; args=(29,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 25; args=(25,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 24; args=(24,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 3; args=(3,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 3; args=(3,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 28; args=(28,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 1; args=(1,)
(0.000) SELECT "content_department"."id", "content_department"."name", "content_department"."description", "content_department"."curator_id", "content_department"."visibility_rank" FROM "content_department" WHERE "content_department"."id" = 28; args=(28,)
(0.000) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 6; args=(6,)
(0.000) SELECT "content_category"."id", "content_category"."name", "content_category"."description" FROM "content_category" WHERE "content_category"."id" = 4; args=(4,)
Wie kann ich eine echte verbinden mit den Informationen, die ich mit Serializer in DRF wollen?
UPDATE:
ich durch Anschluss an die Beratung auf this Blog-Eintrag haben verwalten, um die Abfragezeit in zwei Hälften geschnitten, hier meine aktualisiert Serializer und die Aussicht sind, die sie verwenden:
class DetailedLinkedContentSerializer(serializers.HyperlinkedModelSerializer):
category = CategorySerializer()
department_query = Department.objects.all()
department_query = DepartmentSerializer.setup_eager_loading(department_query)
department = DepartmentSerializer(department_query)
# department = DepartmentSerializer()
type = serializers.SerializerMethodField()
class Meta:
fields = '__all__'
model = LinkedContent
def get_type(self, obj):
return 'link'
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('category', 'department')
return queryset
class DetailedFileContentSerializer(serializers.HyperlinkedModelSerializer):
category = CategorySerializer()
department_query = Department.objects.all()
department_query = DepartmentSerializer.setup_eager_loading(department_query)
department = DepartmentSerializer(department_query)
# department = DepartmentSerializer()
link_url = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
class Meta:
fields = '__all__'
model = FileContent
def get_link_url(self, obj):
return obj.file.url
def get_type(self, obj):
return obj.file_type
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('category', 'department')
return queryset
und meine Ansicht, die Verwendung dieser Serializer macht:
class DetailedContentView(views.APIView):
permission_classes = [IsAuthenticated, ContentCuratorOrReadOnly, IsGroupMember, ]
def get(self, request, *args, **kwargs):
context = {"request": request}
linked_content = LinkedContent.objects.all()
file_content = FileContent.objects.all()
# this line is newly added
linked_content = DetailedLinkedContentSerializer.setup_eager_loading(linked_content)
# this line too
file_content = DetailedLinkedContentSerializer.setup_eager_loading(file_content)
linked_content_serializer = DetailedLinkedContentSerializer(linked_content, many=True, context=context)
file_content_serializer = DetailedFileContentSerializer(file_content, many=True, context=context)
response = linked_content_serializer.data + file_content_serializer.data
response = sorted(response, key=lambda x: (x['department']['visibility_rank'], x['visibility_rank']))
return Response(response)
jedoch meine Lösung prefetch meine Benutzer Serializer in meiner Abteilung Serializer scheint nicht mach den Trick. Insbesondere wird nach meiner Abteilung Serializer Aktualisierung:
class DepartmentSerializer(serializers.HyperlinkedModelSerializer):
curator = UserSerializer()
class Meta:
model = Department
fields = '__all__'
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('curator')
return queryset
die folgenden Zeilen:
department_query = Department.objects.all()
department_query = DepartmentSerializer.setup_eager_loading(department_query)
department = DepartmentSerializer(department_query)
scheinen nicht meine Kuratoren zu werden Prefetching, wie ich will.
class EagerLoadingMixin:
@classmethod
def setup_eager_loading(cls, queryset):
if hasattr(cls, "_SELECT_RELATED_FIELDS"):
queryset = queryset.select_related(*cls._SELECT_RELATED_FIELDS)
if hasattr(cls, "_PREFETCH_RELATED_FIELDS"):
queryset = queryset.prefetch_related(*cls._PREFETCH_RELATED_FIELDS)
return queryset
und hinzugefügt 'department__curator'
auf meine Liste der Prefetch-Felder:
Haben Sie versucht, [select_related] (https://docs.djangoproject.com/en/1.11/ref/models/querysets/#select-related) oder [prefetch_related] (https://docs.djangoproject.com) zu verwenden /de/1.11/ref/models/querysets/#prefetch-related) auf Ihrer Anfrage in Ihrer Sicht? Diese sollten Daten vorab laden, um eine neue Anfrage für jeden Eintrag und jede Beziehung zu vermeiden. –
Ich arbeite gerade daran und ich bin dabei, meine Frage zu aktualisieren. – DragonBobZ