web-dev-qa-db-ja.com

Serializerのcreate()およびModelViewsetのcreate()perform_create()を使用する場合

モデルオブジェクトの作成に関するDjango-rest-frameworkのドキュメントを明確にしたいと思います。これまでのところ、このようなイベントを処理する方法には3つのアプローチがあることがわかりました。

  1. シリアライザーのcreate()メソッド。 ドキュメント

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. ModelViewset create()メソッド。 ドキュメント

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. ModelViewset perform_create()メソッド。 ドキュメント

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

これらの3つのアプローチは、アプリケーション環境に応じて重要です。

しかし、各create() / perform_create()関数を使用する必要がある場合は??一方で、modelviewsetのcreate()とシリアライザーのcreate()という1つのポストリクエストに対して2つのcreateメソッドが呼び出されるというアカウントが見つかりました。

うまくいけば、誰もが説明するために彼らの知識の一部を共有し、これが私の開発プロセスで確実に非常に役立つことを願っています。

62
Roel
  1. create(self, validated_data)を使用してオブジェクトに追加の詳細を追加してから、**validated_dataと同様に各モデルフィールドに「prod」値を保存します。理想的には、この形式の「プロディング」は1つの場所でのみ行いたいので、createCommentSerializerメソッドが最適な場所です。さらに、アカウントを自分のデータベースに保存する直前に、外部apiを呼び出してユーザーアカウントを作成することもできます。このcreate関数は、ModelViewSetと組み合わせて使用​​する必要があります。常に考える-「薄いビュー、厚いシリアライザー」。

例:

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. ModelViewSetcreate(self, request, *args, **kwargs)関数は、CreateModelMixinの親であるModelViewSetクラスで定義されています。 CreateModelMixinの主な機能は次のとおりです。

    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()
    

ご覧のとおり、上記のcreate関数は、シリアライザーで検証を呼び出し、正しい応答を生成します。この背後にある美しさは、アプリケーションロジックを分離でき、ありふれた繰り返しの検証呼び出しや応答出力の処理について心配する必要がないことです:)。これは、シリアライザー(特定のアプリケーションロジックが存在する可能性のある場所)にあるcreate(self, validated_data)と組み合わせて非常にうまく機能します。

  1. 今、あなたは尋ねるかもしれません、なぜ私たちは1行のコードだけで別のperform_create(self, serializer)関数を持っているのですか!?!?さて、この背後にある主な理由は、save関数を呼び出すときにカスタマイズ可能にすることです。 saveserializer.save(owner=self.request.user)を呼び出す前に追加のデータを提供したい場合があります。また、perform_create(self, serializer)がない場合は、create(self, request, *args, **kwargs)をオーバーライドする必要があります。重くて退屈な仕事。

お役に立てれば!

82
Apoorv Kansal