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)
and .update(self, validated_data)
used for in the serializer. As I understand, CRUD only calls the 4 main methods in viewsets.ModelViewSet
: create()
, retrive()
, update()
, and destroy()
.
I also have already tried to debug and print out stuff to see when the .create()
and .update()
methods are called in both ModelViewSet
and ModelSerializer
. Apparently, only the methods in ModelViewSet
are called when I do the HTTP verbs. However, for ModelSerializer
, I don't see any calls in those 2 methods. I just want to know what are those methods used for in ModelSerializer
since I see that people override those methods a lot in the serializer.
Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With