wake-up-neo.com

Verwendung von create () von Serializer und create () von ModelViewset perform_create ()

Ich möchte die angegebene Dokumentation von Django-rest-framework Bezüglich der Erstellung eines Modellobjekts verdeutlichen. Bisher habe ich festgestellt, dass es drei Ansätze gibt, wie man mit solchen Ereignissen umgeht.

  1. Die create() -Methode des Serializers. Hier ist die Dokumentation

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. Die ModelViewset create() -Methode. Dokumentation

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. Die ModelViewset perform_create() -Methode. Dokumentation

    class SnippetViewSet(viewsets.ModelViewSet):
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)
    

Diese drei Ansätze sind abhängig von Ihrer Anwendungsumgebung wichtig.

Aber WANN müssen wir jede create() / perform_create() -Funktion verwenden ??. Auf der anderen Seite habe ich einen Account gefunden, bei dem zwei Erstellungsmethoden für eine einzelne Post-Anfrage aufgerufen wurden: die create() des modelviewsets und die create() des serializers.

Hoffentlich würde jeder etwas von seinem Wissen teilen, um es zu erklären, und dies wird sicherlich sehr hilfreich in meinem Entwicklungsprozess sein.

62
Roel
  1. Sie würden create(self, validated_data) verwenden, um dem Objekt zusätzliche Details hinzuzufügen, bevor Sie AND "prod" -Werte in jedem Modellfeld speichern, genau wie dies **validated_data Tut. Idealerweise möchten Sie diese Form des "Stapelns" nur an EINEM Ort ausführen, daher ist die create -Methode in Ihrem CommentSerializer der beste Ort. Darüber hinaus möchten Sie möglicherweise auch externe APIs aufrufen, um Benutzerkonten auf ihrer Seite zu erstellen, bevor Sie Ihre Konten in Ihrer eigenen Datenbank speichern. Sie sollten diese create -Funktion in Verbindung mit ModelViewSet verwenden. Denken Sie immer an "Thin Views, Thick Serializers".

Beispiel:

def create(self, validated_data):
    email = validated.data.get("email", None)
    validated.pop("email") 
    # Now you have a clean valid email 
    # You might want to call an external API or modify another table
    # (eg. keep track of number of accounts registered.) or even
    # make changes to the email format.

    # Once you are done, create the instance with the validated data
    return models.YourModel.objects.create(email=email, **validated_data)
  1. Die Funktion create(self, request, *args, **kwargs) in ModelViewSet wird in der Klasse CreateModelMixin definiert, die das übergeordnete Element von ModelViewSet ist. Die Hauptfunktionen von CreateModelMixin sind:

    from rest_framework import status
    from rest_framework.response import Response
    
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
    def perform_create(self, serializer):
        serializer.save()
    

Wie Sie sehen, sorgt die obige Funktion create dafür, dass die Validierung auf Ihrem Serializer aufgerufen und die richtige Antwort ausgegeben wird. Das Schöne daran ist, dass Sie jetzt Ihre Anwendungslogik isolieren können und sich NICHT um die alltäglichen und sich wiederholenden Validierungsaufrufe und die Verarbeitung der Antwortausgaben kümmern müssen :). Dies funktioniert sehr gut in Verbindung mit der Funktion create(self, validated_data), die im Serializer enthalten ist (wo sich möglicherweise Ihre spezifische Anwendungslogik befindet).

  1. Nun könnten Sie sich fragen, warum wir eine separate perform_create(self, serializer) -Funktion mit nur einer Codezeile haben!?!? Der Hauptgrund dafür ist, die Anpassbarkeit beim Aufrufen der Funktion save zu ermöglichen. Möglicherweise möchten Sie zusätzliche Daten angeben, bevor Sie save(wie serializer.save(owner=self.request.user) aufrufen, und wenn wir perform_create(self, serializer) nicht hätten, müssten Sie Überschreiben Sie die Funktion create(self, request, *args, **kwargs), und das macht den Zweck zunichte, dass Mixins die schwere und langweilige Arbeit erledigen.

Hoffe das hilft!

82
Apoorv Kansal