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

Roe*_*oel 65 python django serialization django-rest-framework

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

  1. Serializer的create()方法.这是文档

    class CommentSerializer(serializers.Serializer):
    
        def create(self, validated_data):
            return Comment.objects.create(**validated_data)
    
    Run Code Online (Sandbox Code Playgroud)
  2. ModelViewset create()方法.文档

    class AccountViewSet(viewsets.ModelViewSet):
    
        queryset = Account.objects.all()
        serializer_class = AccountSerializer
        permission_classes = [IsAccountAdminOrReadOnly]
    
    Run Code Online (Sandbox Code Playgroud)
  3. ModelViewset perform_create()方法.文档

    class SnippetViewSet(viewsets.ModelViewSet):
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)
    
    Run Code Online (Sandbox Code Playgroud)

根据您的应用程序环境,这三种方法很重要.

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

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

Apo*_*sal 88

  1. create(self, validated_data)在将AND"prod"值保存到每个模型字段之前,您将使用向对象添加任何额外的详细信息**validated_data.理想情况下,你只想在一个地方做这种形式的"刺激",所以create你的方法CommentSerializer是最好的地方.除此之外,您可能还想在将帐户保存到自己的数据库之前调用外部apis来创建用户帐户.您应该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)
Run Code Online (Sandbox Code Playgroud)
  1. 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()
    
    Run Code Online (Sandbox Code Playgroud)

如您所见,上述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 无法完成繁重而枯燥的工作.

希望这可以帮助!

  • 那么这段代码 `return models.YourModel.objects.create(email=email, **validated_data)` 将保存数据库中的数据,对吗? (2认同)
  • 因此,序列化器本身中的“create”函数**仅**在执行“serializer.save()”时被调用。在 (`AccountViewSet`) 内的 `create(self, request)` 函数中,您根本没有调用 `serializer.save()`,因此,唯一的实例创建是通过以下调用进行的:`Account.objects.create_user (**serializer.validated_data)`。 (2认同)

Ben*_*vis 9

虽然 Apoorv 的答案是正确且非常详细的,但这里有一个快速答案:

  • perform_create()当您想要更改对象创建方式的“幕后”行为时覆盖。例如,在创建对象之前或之后执行一些额外的操作。
  • create()当您想要修改响应时覆盖。例如,如果您想重新构造响应,添加额外的数据、额外的标头等。

  • 哪个 create() 方法?属于序列化器还是属于 ModelViewSet? (6认同)