Python 何时使用 Serializer 的 create() 和 ModelViewset 的 create() perform_create()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41094013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:26:24  来源:igfitidea点击:

When to use Serializer's create() and ModelViewset's create() perform_create()

pythondjangoserializationdjango-rest-framework

提问by Roel

I want to clarify the given documentation of django-rest-frameworkregarding the creation of a model object. So far I found that there are 3 approaches on how to handle such events.

我想澄清django-rest-framework有关创建模型对象的给定文档。到目前为止,我发现有 3 种方法可以处理此类事件。

  1. The Serializer's create()method. Here is the documentation

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. The ModelViewset create()method. Documentation

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. The ModelViewset perform_create()method. Documentation

    class SnippetViewSet(viewsets.ModelViewSet):
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)
    
  1. 序列化程序的create()方法。这是文档

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
  2. ModelViewsetcreate()方法。文档

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
  3. ModelViewsetperform_create()方法。文档

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

These three approaches are important depending on your application environment.

这三种方法很重要,具体取决于您的应用程序环境。

But WHEN do we need to use each create() / perform_create()function??. On the other hand I found some account that two create methods were called for a single post request the modelviewset's create()and serializer's create().

但是我们什么时候需要使用每个create() / perform_create()函数??。另一方面,我发现一些帐户为模型视图集create()和序列化程序的单个帖子请求调用了两个创建方法create()

Hopefully anyone would share some of their knowledge to explain and this will surely be very helpful in my development process.

希望任何人都可以分享他们的一些知识来解释,这肯定会对我的开发过程非常有帮助。

回答by Apoorv Kansal

  1. You would use create(self, validated_data)to add any extra details into the object before saving AND "prod" values into each model field just like **validated_datadoes. Ideally speaking, you want to do this form of "prodding" only in ONE location so the createmethod in your CommentSerializeris the best place. On top of this, you might want to also call external apis to create user accounts on their side just before saving your accounts into your own database. You should use this createfunction in conjunction withModelViewSet. Always think - "Thin views, Thick serializers".
  1. create(self, validated_data)在将 AND “prod” 值保存到每个模型字段之前,您将使用将任何额外的详细信息添加到对象中,就像这样**validated_data做一样。理想情况下,您只想在一个位置进行这种“刺激”形式,因此create您的方法CommentSerializer是最佳位置。最重要的是,您可能还想在将您的帐户保存到您自己的数据库之前调用外部 apis 在他们这边创建用户帐户。您应该将此create功能与ModelViewSet. 始终认为 - “瘦视图,厚序列化器”。

Example:

例子:

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)
  1. The create(self, request, *args, **kwargs)function in the ModelViewSetis defined in the CreateModelMixinclass which is the parent of ModelViewSet. CreateModelMixin's main functions are these:

    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()
    
  1. 中的create(self, request, *args, **kwargs)函数在作为的父类的类中ModelViewSet定义。的主要功能是这些:CreateModelMixinModelViewSetCreateModelMixin

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

As you can see, the above createfunction takes care of calling validation on your serializer and producing the correct response. The beauty behind this, is that you can now isolate your application logic and NOT concern yourself about the mundane and repetitive validation calls and handling response output :). This works quite well in conjuction with the create(self, validated_data)found in the serializer (where your specific application logic might reside).

如您所见,上述create函数负责在序列化程序上调用验证并生成正确的响应。这背后的美妙之处在于,您现在可以隔离您的应用程序逻辑,而不必担心平凡和重复的验证调用和处理响应输出:)。这与create(self, validated_data)在序列化程序中找到的(您的特定应用程序逻辑可能驻留的位置)结合使用效果很好。

  1. Now you might ask, why do we have a separate perform_create(self, serializer)function with just one line of code!?!? Well, the main reason behind this is to allow customizeability when calling the savefunction. You might want to supply extra data before calling save(like serializer.save(owner=self.request.user)and if we didn't have perform_create(self, serializer), you would have to override the create(self, request, *args, **kwargs)and that just defeats the purpose of having mixins doing the heavy and boring work.
  1. 现在你可能会问,为什么我们有一个单独的perform_create(self, serializer)函数,只有一行代码!?!?嗯,这背后的主要原因是在调用save函数时允许自定义。你可能想在调用之前提供额外的数据save(比如serializer.save(owner=self.request.user),如果我们没有perform_create(self, serializer),你将不得不覆盖create(self, request, *args, **kwargs),这只会违背让 mixin 做繁重而无聊的工作的目的。

Hope this helps!

希望这可以帮助!