I\'m currently implementing djangorestframework for my app RESTful API. After playing around with it, I still do not clearly understand what .create(self, validated_data)<
In the rest-api design create, read, update and delete is a standard. There is not quite big difference in create and update.
Please refer to this and
see create() method will create an item.
and
update() method need to specify which item to be updated.
You really must split things between the views and the serializer.
The Serializer
is a standalone object. It is used for converting a Django model (or any kind of python datastructure, actually) into a serialized form, and the other way around.
You may use it as such, wherever you want. It does not even need an actual HTTP request as long as you don't need URIs in your output.
The ModelSerializer
subclass is a specialized kind of Serializer
that adds "load-from-model" and "save-to-model" functionality.
The "save-to-model" entry point is the save()
method. For easier overriding, its default implementation will delegate its work to either the create()
or ̀update()
method of the serializer, depending on whether it is creating a new model instance, or updating one.
The purpose of that is customization: it gives you, the developer, the option to override just the create method, just the update method, or common behavior. For instance, it allows you to do this kind of things:
def save(self, **kwargs):
# Will be done on every save
kwargs['last_changed'] = timezone.now()
return super().save(**kwargs)
def create(self, instance, data):
# Will only be done if a new object is being created
data['initial_creation'] = timezone.now()
return super().create(instance, data)
That's a basic example. There, the last_changed
field will be set every time an object is saved, be it a creation or an update.
As a sidenote, you probably do not want to do that. Things such as setting "last_changed" fields should live in the view, not in the serializer.
In a completely different place, Django REST framework supplies Viewsets
. Those are an organized collection of views, revolving around implementing a CRUD API for a model.
As such, it structures it functionality into a set of methods, namely create()
, retrieve()
/list()
, update()
and delete()
.
The main point being: there is no connection whatsoever between the viewset's create()
method and the serializer's create()
method.
It just happens that the default implementation of the viewset's methods uses a ModelSerializer
and that the default implementation of that serializer's save()
method delegates the job to methods that have the same name.
By the way, about the last_changed
example, here is how you would do it in the view:
def perform_create(self, serializer):
now = timezone.now()
serializer.save(initial_creation=now, last_changed=now)
def perform_update(self, serializer):
serializer.save(last_changed=timezone.now())
That's functionally equivalent to the example above, but lives in the viewset.
So back to your question, the specific thing you should override depends on which object is responsible for the task you want to add.
Serializer
's methods.Viewset
's methods.As a hint, you may ask yourself the following question: if I use the same serializer in another place (maybe another viewset), should it always display that behavior?
I finally understand how the .create()
and .update()
work in Serializer
(especially ModelSerializer
) and how they are connected to Viewsets
(especially ModelViewSet
). I just want clarify the concept more clearly if someone comes to this question.
Basically, the 4 methods CRUD in ModelViewSet
: .create()
, .retrieve()
, .update()
, and .destroy()
will handle the calls from HTTP verbs. By default, the .create()
and .update()
from ModelViewSet will call the .create()
and .update()
from ModelSerializer by calling the .save()
method from the BaseSerializer class.
The save() method will then determine whether it will call .create()
or .update()
in ModelSerializer by determining whether the object self.instance
exists or not.