Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the different between save(), create() and update () in django rest framework?

I m confused when making api on django rest framework using serializers, please tell me exact different between save(), create() and update() methods, my code sample is as follow,

View.py

class AddUser(views.APIView):
    serializer_class = UserForAdminSerializer

    def post(self, request, *args, **kwargs):

        serializer = UserForAdminSerializer(data=request.data)

        if serializer.is_valid():

            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py

class UserForAdminSerializer(serializers.ModelSerializer):

    first_name = serializers.CharField(max_length=30)
    last_name = serializers.CharField(max_length=30)
    name = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=20, style={'input_type': 'password'})

    class Meta:
        model = User
        fields = ('id', 'url', 'first_name', 'last_name', 'name', 'username', 'email', 'password',
                  'total_exp_year', 'total_exp_month', 'voteup_count', 'is_featured',
                  'is_active', 'headline', 'description', 'profile_picture', )

    def create(self, validated_data):
        password = validated_data.pop('password', None)
        instance = self.Meta.model(**validated_data)
        if password is not None:
            instance.set_password(password)
        instance.save()
        return instance

on the above code in view.py file i m used save() method and serializers.py using save() or update() method so please explain me how it's working and clear my confusion between save() and create()

like image 922
Ashok Kumar Avatar asked Jul 14 '17 10:07

Ashok Kumar


People also ask

What does serializer save () do?

So everytime you call Serializer's save() , you get an instance of whatever data you are serializing. comment here is an instance. Passing an instance in a serializer is telling the serializer that you want to update this instance. So calling save will then call self.

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

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.

Why do we use Serializers in Django REST Framework?

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.

How do you pass extra context data to Serializers in Django REST Framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.


2 Answers

Usually the best way to get a good understanding of the code is to actually read it, so let's take a look at the source:

class BaseSerializer(Field):
    ...
    def update(self, instance, validated_data):
        raise NotImplementedError('`update()` must be implemented.')

    def create(self, validated_data):
        raise NotImplementedError('`create()` must be implemented.')

    def save(self, **kwargs):
        ...
        ... a lot of assertions and safety checks ...
        ... 

        validated_data = dict(
            list(self.validated_data.items()) +
            list(kwargs.items())
        )

        if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            ....
        else:
            self.instance = self.create(validated_data)
            ...
        return self.instance

Okay, so, in this base class methods update and create are left to concrete subclasses to be implemented (as details will vary for serializers such as ListSerializer or ModelSerializer).

However, save is implemented and it basically just checks if object is new or existing (if self.instance is not None) and calls update or create respectively. This code will be called in every other serializer.

Let's take a look at concrete subclass:

def create(self, validated_data):
    ...
    ... some stuff happening
    ...

    try:
        # Here is the important part! Creating new object!
        instance = ModelClass.objects.create(**validated_data)
    except TypeError:
        raise TypeError(msg)

    # Save many-to-many relationships after the instance is created.
    if many_to_many:
        for field_name, value in many_to_many.items():
            set_many(instance, field_name, value)

    return instance


def update(self, instance, validated_data):
    raise_errors_on_nested_writes('update', self, validated_data)
    info = model_meta.get_field_info(instance)

    # Simply set each attribute on the instance, and then save it.
    # Note that unlike `.create()` we don't need to treat many-to-many
    # relationships as being a special case. During updates we already
    # have an instance pk for the relationships to be associated with.
    for attr, value in validated_data.items():
        if attr in info.relations and info.relations[attr].to_many:
            set_many(instance, attr, value)
        else:
            setattr(instance, attr, value)
    instance.save()

    return instance

As you can see both create and update call set_many(instance, attr, value) to set values for object attributes. However, create does one critical call before: ModelClass.objects.create(**validated_data). This actually creates new instance.

I hope this clears it up a bit.

like image 176
Siegmeyer Avatar answered Sep 18 '22 15:09

Siegmeyer


In Django Rest Framework documentation they explained very clearly when to override save method and when create method.

I am posting their explanation here for your convenience


In some cases the .create() and .update() method names may not be meaningful. For example, in a contact form we may not be creating new instances, but instead sending an email or other message. In these cases you might instead choose to override .save() directly, as being more readable and meaningful.
Example:-

class ContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()

    def save(self):
        email = self.validated_data['email']
        message = self.validated_data['message']
        send_email(from=email, message=message)
like image 27
Arpit Svt Avatar answered Sep 18 '22 15:09

Arpit Svt