1. ホーム
  2. python

[解決済み] Serializer の create() と ModelViewset の perform_create() はいつ使うか?

2022-07-02 02:11:23

質問

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

  1. シリアライザーの create() メソッドを使用します。ここでは ドキュメント

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
    
  2. モデルビューセット create() メソッドを使用します。 ドキュメンテーション

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
    
  3. モデルビューセット perform_create() メソッドを使用します。 ドキュメンテーション

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

これら3つのアプローチは、アプリケーションの環境に応じて重要です。 しかし、どのような場合にそれぞれの create() / perform_create() 関数を使う必要があるのでしょうか?一方、1つのポストリクエストに対して2つのcreateメソッドが呼び出されているアカウントを発見しました。 ModelViewSet 's create() とシリアライザの create() .

どのように解決するのですか?

  1. あなたは create(self, validated_data) のように各モデルフィールドに AND "prod" 値を保存する前に、オブジェクトに余分な詳細を追加することができます。 **validated_data と同じように各モデルフィールドに値を追加します。理想を言えば、このようなquot;prodding"は1つの場所でだけ行いたいので create メソッドで CommentSerializer が最適な場所です。これに加えて、アカウントを自分のデータベースに保存する直前に、外部のapiを呼び出してユーザーアカウントを作成したい場合もあるでしょう。その場合は、次のようにします。 create 関数と一緒に ModelViewSet . 常に「薄いビュー、厚いシリアライザー」と考えてください。

    def create(self, validated_data):
        email = validated_data.get("email", None)
        validated.pop("email") 
        # Now you have a clean valid email string 
        # 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)
    
    
  2. create(self, request, *args, **kwargs) の中の関数 ModelViewSet の中で定義されている 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) と組み合わせてもうまくいきます。

  3. 今、あなたは、なぜ私たちが別の perform_create(self, serializer) 関数をたった1行のコードで作ったのか?という疑問があるかもしれません。 save 関数を呼び出す際にカスタマイズできるようにするためです。を呼び出す前に余分なデータを供給したいと思うかもしれません。 save (例えば serializer.save(owner=self.request.user) で、もし私たちが perform_create(self, serializer) がなければ create(self, request, *args, **kwargs) をオーバーライドすることになり、重くて退屈な作業をミキシンにやらせるという趣旨から外れてしまいます。