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 approach on how to handle such events.
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)
This three approach is important depending to your application environment.
But WHEN do we need to use each create() / perform_create()
function??. In 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()
.
Hopefully anyone would share some of their knowledge to explain and this will surely be very helpful in my development process.
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".Example:
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: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 thecreate(self, validated_data)
found in the serializer (where your specific application logic might reside).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.Hope this helps!