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

我想澄清一下关于创建模型对象的 Django-rest-Framework 的给定文档。到目前为止,我发现有3种方法来处理这样的事件。

  1. Serializer 的 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)
    

根据应用程序环境的不同,这三种方法都很重要。 但是我们什么时候需要使用每个 create() / perform_create()函数呢?另一方面,我发现一些帐户,为一个帖子请求 ModelViewSetcreate()和序列化程序的 create()调用了两个 create 方法。

59248 次浏览
  1. 在将 AND“ prod”值保存到每个模型字段之前,您可以使用 create(self, validated_data)向对象中添加任何额外的细节,就像 **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 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. ModelViewSet中的 create(self, request, *args, **kwargs)函数是在 CreateModelMixin类中定义的,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)函数只有一行代码! ? ! ?这背后的主要原因是在调用 save函数时允许可定制性。你可能想在调用 save (如 serializer.save(owner=self.request.user)之前提供额外的数据,如果我们没有 perform_create(self, serializer),你就必须覆盖 create(self, request, *args, **kwargs),这就违背了混合器做繁重而无聊的工作的目的。

虽然阿波尔夫的回答是正确的,而且非常详细,但这里有一个快速的答案:

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