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
When to use Serializer's create() and ModelViewset's create() perform_create()
提问by Roel
I want to clarify the given documentation of django-rest-framework
regarding 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 种方法可以处理此类事件。
The Serializer's
create()
method. Here is the documentationclass CommentSerializer(serializers.Serializer): def create(self, validated_data): return Comment.objects.create(**validated_data)
The ModelViewset
create()
method. Documentationclass AccountViewSet(viewsets.ModelViewSet): queryset = Account.objects.all() serializer_class = AccountSerializer permission_classes = [IsAccountAdminOrReadOnly]
The ModelViewset
perform_create()
method. Documentationclass SnippetViewSet(viewsets.ModelViewSet): def perform_create(self, serializer): serializer.save(owner=self.request.user)
序列化程序的
create()
方法。这是文档class CommentSerializer(serializers.Serializer): def create(self, validated_data): return Comment.objects.create(**validated_data)
ModelViewset
create()
方法。文档class AccountViewSet(viewsets.ModelViewSet): queryset = Account.objects.all() serializer_class = AccountSerializer permission_classes = [IsAccountAdminOrReadOnly]
ModelViewset
perform_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
- 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_data
does. Ideally speaking, you want to do this form of "prodding" only in ONE location so thecreate
method in yourCommentSerializer
is 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 thiscreate
function in conjunction withModelViewSet
. Always think - "Thin views, Thick serializers".
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)
The
create(self, request, *args, **kwargs)
function in theModelViewSet
is defined in theCreateModelMixin
class which is the parent ofModelViewSet
.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()
中的
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()
As you can see, the above create
function 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)
在序列化程序中找到的(您的特定应用程序逻辑可能驻留的位置)结合使用效果很好。
- 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 thesave
function. You might want to supply extra data before callingsave
(likeserializer.save(owner=self.request.user)
and if we didn't haveperform_create(self, serializer)
, you would have to override thecreate(self, request, *args, **kwargs)
and that just defeats the purpose of having mixins doing the heavy and boring work.
- 现在你可能会问,为什么我们有一个单独的
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!
希望这可以帮助!