何时使用序列化器的create()和ModelViewset的create()perform_create()


102

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

  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)
    

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

但是什么时候我们需要使用每个create() / perform_create()函数?另一方面,我发现有人要求为单个发布请求调用modelviewsetcreate()和serializer的两个create方法create()

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

Answers:


131
  1. 你会使用create(self, validated_data)节约型和“刺”的价值观为就像每个模型前场添加任何额外的细节到对象**validated_data一样。理想情况下,您只想在一个位置执行这种“探测”形式,因此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)
  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()
    

如您所见,以上create函数负责在序列化程序上调用验证并产生正确的响应。这样做的好处是,您现在可以隔离应用程序逻辑,而不必担心平凡和重复的验证调用以及处理响应输出:)。与create(self, validated_data)序列化器(您的特定应用程序逻辑所在的位置)中的结合使用时,这可以很好地工作。

  1. 现在您可能会问,为什么我们perform_create(self, serializer)只有一行代码才有一个单独的函数!好吧,这背后的主要原因是在调用save函数时允许自定义。您可能想要在调用之前提供额外的数据save (例如serializer.save(owner=self.request.user),如果我们没有perform_create(self, serializer),那么您将不得不重写,create(self, request, *args, **kwargs)而这违背了让mixin进行繁重而乏味的工作的目的。

希望这可以帮助!


嗨!感谢您分享知识!关于create(self, validated_data)序列化程序,这意味着它专注于数据验证逻辑吗?还有更多可以帮助将给定的序列化器的数据返回给响应的权利吗?
Roel

1
目前还没有,您已经通过了所有验证。我说的是您可能要如何在将验证数据保存到数据库之前自定义验证数据。我将在答案中举例说明。
Apoorv Kansal

1
不用担心-只是添加了一个示例以提供更多上下文。
Apoorv Kansal

1
是的,这是将您的对象保存到数据库中的最后一行
Apoorv Kansal 16/12/12

1
因此,在执行时才调用create序列化程序本身中的函数。在()中的函数中,您根本没有调用,因此,唯一的实例创建是通过以下调用进行的:。serializer.save()create(self, request)AccountViewSetserializer.save()Account.objects.create_user(**serializer.validated_data)
Apoorv Kansal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.