encode / django-rest-framework

Web APIs for Django. 🎸
https://www.django-rest-framework.org
Other
28.19k stars 6.81k forks source link

More Concise way to Update Instances!! #9123

Closed PARTHIB-DEB closed 10 months ago

PARTHIB-DEB commented 11 months ago

A more Short Way to Update Instances

-[ ] Updation Method in SAVING INSTANCE

    def update(self, instance, validated_data):
        if 'author' in validated_data:
            instance.cname=validated_data['author']
        if 'brief' in validated_data:
            instance.cname=validated_data['brief']
        if 'cid' in validated_data:
            raise serializers.ValidationError('cid IS UNIQUE AND IT CANNOT BE CHANGED')
        else:
            raise serializers.ValidationError('INVALID FIELD GIVEN')
        instance.save()
        return instance
PARTHIB-DEB commented 11 months ago

I have changes the code of updation , provided in the docs in a more clean way.

auvipy commented 11 months ago

can you share more context on which part of docs you are suggesting?

PARTHIB-DEB commented 11 months ago

After Deserializing object there is a column named saving instances , there you can se the code

FraCata00 commented 10 months ago

Please give more info to explain this @PARTHIB-DEB, add entire serializer class, there is a serializers.ModelSerializer or serializers.Serializers base class?

PARTHIB-DEB commented 10 months ago

This example is on the docs and I have changed it a little to make it more precise and easy to understand that which part ids going to update image

PARTHIB-DEB commented 10 months ago
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueTogetherValidator
from django.contrib.auth import authenticate,login,logout

class UserSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField(read_only=True)
    class Meta:
        model=User
        fields=('username','email','password','confirm_password','first_name','last_name')
        validators = [
            UniqueTogetherValidator(
                queryset=User.objects.all(),
                fields=['username','email','password']
            )
        ]

    def update(self, instance, validated_data):
        if 'username' in validated_data:
            instance.username=validated_data['username']
        if 'email' in validated_data:
            instance.email=validated_data['email']
        if 'password' in validated_data:
            instance.password=validated_data['password']
        if 'first_name' in validated_data:
            instance.first_name=validated_data['first_name']
        if 'last_name' in validated_data:
            instance.last_name=validated_data['last_name']
        if 'last_login' in validated_data:
            instance.last_login=validated_data['last_login']
        if 'is_superuser' in validated_data:
            instance.is_superuser=validated_data['is_superuser']
        else:
            raise serializers.ValidationError('INVALID FIELD GIVEN')
        instance.save()
        return instance

Its my own code of a project

PARTHIB-DEB commented 10 months ago

Please give more info to explain this @PARTHIB-DEB, add entire serializer class, there is a serializers.ModelSerializer or serializers.Serializers base class?

Modelserializer

FraCata00 commented 10 months ago

I think there is a bad idea to use the django user model for this, It's not your job to edit data with this case, please look better way like authentication method of DRF or djoser https://djoser.readthedocs.io

PARTHIB-DEB commented 10 months ago

I think there is a bad idea to use the django user model for this, It's not your job to edit data with this case, please look better way like authentication method of DRF or djoser https://djoser.readthedocs.io

I think you are not getting what I told. I am just trying to change the way of Updating fields showed in the docs. There is nothing related to User model. Just the step in the docs and in my sample code (see those if clauses)

FraCata00 commented 10 months ago
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueTogetherValidator
from django.contrib.auth import authenticate,login,logout

class UserSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField(read_only=True)
    class Meta:
        model=User
        fields=('username','email','password','confirm_password','first_name','last_name')
        validators = [
            UniqueTogetherValidator(
                queryset=User.objects.all(),
                fields=['username','email','password']
            )
        ]

    def update(self, instance, validated_data):
        if 'username' in validated_data:
            instance.username=validated_data['username']
        if 'email' in validated_data:
            instance.email=validated_data['email']
        if 'password' in validated_data:
            instance.password=validated_data['password']
        if 'first_name' in validated_data:
            instance.first_name=validated_data['first_name']
        if 'last_name' in validated_data:
            instance.last_name=validated_data['last_name']
        if 'last_login' in validated_data:
            instance.last_login=validated_data['last_login']
        if 'is_superuser' in validated_data:
            instance.is_superuser=validated_data['is_superuser']
        else:
            raise serializers.ValidationError('INVALID FIELD GIVEN')
        instance.save()
        return instance

Its my own code of a project

Please, it's not good point update the User resource like this

PARTHIB-DEB commented 10 months ago
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueTogetherValidator
from django.contrib.auth import authenticate,login,logout

class UserSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField(read_only=True)
    class Meta:
        model=User
        fields=('username','email','password','confirm_password','first_name','last_name')
        validators = [
            UniqueTogetherValidator(
                queryset=User.objects.all(),
                fields=['username','email','password']
            )
        ]

    def update(self, instance, validated_data):
        if 'username' in validated_data:
            instance.username=validated_data['username']
        if 'email' in validated_data:
            instance.email=validated_data['email']
        if 'password' in validated_data:
            instance.password=validated_data['password']
        if 'first_name' in validated_data:
            instance.first_name=validated_data['first_name']
        if 'last_name' in validated_data:
            instance.last_name=validated_data['last_name']
        if 'last_login' in validated_data:
            instance.last_login=validated_data['last_login']
        if 'is_superuser' in validated_data:
            instance.is_superuser=validated_data['is_superuser']
        else:
            raise serializers.ValidationError('INVALID FIELD GIVEN')
        instance.save()
        return instance

Its my own code of a project

Please, it's not good point update the User resource like this

can you tell me the reason why?

PARTHIB-DEB commented 10 months ago

The data is already validated...after validations I am doing this. So its not raw actually

FraCata00 commented 10 months ago

I think there is a bad idea to use the django user model for this, It's not your job to edit data with this case, please look better way like authentication method of DRF or djoser https://djoser.readthedocs.io

I think you are not getting what I told. I am just trying to change the way of Updating fields showed in the docs. There is nothing related to User model. Just the step in the docs and in my sample code (see those if

from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueTogetherValidator
from django.contrib.auth import authenticate,login,logout

class UserSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField(read_only=True)
    class Meta:
        model=User
        fields=('username','email','password','confirm_password','first_name','last_name')
        validators = [
            UniqueTogetherValidator(
                queryset=User.objects.all(),
                fields=['username','email','password']
            )
        ]

    def update(self, instance, validated_data):
        if 'username' in validated_data:
            instance.username=validated_data['username']
        if 'email' in validated_data:
            instance.email=validated_data['email']
        if 'password' in validated_data:
            instance.password=validated_data['password']
        if 'first_name' in validated_data:
            instance.first_name=validated_data['first_name']
        if 'last_name' in validated_data:
            instance.last_name=validated_data['last_name']
        if 'last_login' in validated_data:
            instance.last_login=validated_data['last_login']
        if 'is_superuser' in validated_data:
            instance.is_superuser=validated_data['is_superuser']
        else:
            raise serializers.ValidationError('INVALID FIELD GIVEN')
        instance.save()
        return instance

Its my own code of a project

Please, it's not good point update the User resource like this

can you tell me the reason why?

Because the User layer is a job of django and drf, not yours To update the User resource, before you should read the docs to use your custom user model

FraCata00 commented 10 months ago

The data is already validated...after validations I am doing this. So its not raw actually

To validate the data from a ModelSerializer you shouldn't use custom update method, the ModelSerializer just provide the update and create method equal to the Model, because called ModelSerializer

PARTHIB-DEB commented 10 months ago

sometimes your update method donot work

The data is already validated...after validations I am doing this. So its not raw actually

To validate the data from a ModelSerializer you shouldn't use custom update method, the ModelSerializer just provide the update and create method equal to the Model, because called ModelSerializer

I know, but for some necessities , I think some may do

PARTHIB-DEB commented 10 months ago

This is totally DRF realated I am not even talkinh about any model

FraCata00 commented 10 months ago

Please, use the ModelViewSet and ModelSerializers https://www.django-rest-framework.org/api-guide/serializers/#modelserializer https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset

class MyModelSerializer(serializers.ModelSerializer):

    class Meta:
        model = Currency
        fields = ["id", "company", "name", "owner"]

image

You can spli the serializer and use different serializer in ModelViewSet with def_get_serializer_class base on self.action

Like:

# views.py
from rest_framework import viewsets

class MyModelViewSet(viewsets.ModelViewSet):
      # other 
      def get_serializer_class(self):
           if self.action == "create":
              # return create serializer class
           elif self.action in ["update", "partial_update"]:
             # return the serualizer class made for the PATCH/PUT
           # made last one for the list/retieve action

#serializers.py
class MyModelUpdateSerializer(serializers.ModelSerializer):
    name = serializers.ChoiceField(choices=settings.CURRENCY_CHOICES)
    other_field = serializers.StringRelatedField()

    class Meta:
        model = MyModel
        fields = ["name", "owner"]

class MyModelRetrieveListSerializer(serializers.ModelSerializer):
     class Meta:
        fields = "__all__"

You have more control for action of drf and the HTTP method https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions

PARTHIB-DEB commented 10 months ago

suppose there is a custom model made by me or you. Then can I apply that customized updation?

FraCata00 commented 10 months ago

This is totally DRF realated I am not even talkinh about any model

If you have some validation before update the field, before add a custom def_validate or def_validate_<field_name>, you shouldn't have the update method for this

PARTHIB-DEB commented 10 months ago

so according to you , one should not just customize the native create or updation method on any case of any model whether it is User or any custom model?

PARTHIB-DEB commented 10 months ago

This is totally DRF realated I am not even talkinh about any model

If you have some validation before update the field, before add a custom def_validate or def_validate_<field_name>, you shouldn't have the update method for this

I was using already a given validator. Its just the point of customizing the updation method

FraCata00 commented 10 months ago

Nono, you can do this, but should call the super().update(instance, validated_data) before

def update(self, instance, validated_data):
    instance = super().update(instance, validated_data) # there is an updated instance
    # other your update method if you prefer
    return instance
PARTHIB-DEB commented 10 months ago

Nono, you can do this, but should call the super().update(instance, validated_data) before

def update(self, instance, validated_data):
    instance = super().update(instance, validated_data) # there is an updated instance
    # other your update method if you prefer
    return instance

So if there is an user just want to update a specific field in his/her profile , for that person, would this code properly run?

FraCata00 commented 10 months ago

Or just pop the interessed fields

def update(self, instance, validated_data):
    my_field = validated_data.pop("my_field")
    # if condition or other code
    .....
    return  super().update(instance, validated_data)

or

def update(self, instance, validated_data):
    # MANIPULATE DATA HERE BEFORE INSERTION

    instance = super().update(instance, validated_data)
    # ADD CODE HERE THAT YOU WANT TO VIEW
    return instance
PARTHIB-DEB commented 10 months ago

Or just pop the interessed fields

def update(self, instance, validated_data):
    my_field = validated_data.pop("my_field")
    # if condition or other code
    .....
    return  super().update(instance, validated_data)

or

def update(self, instance, validated_data):
    # MANIPULATE DATA HERE BEFORE INSERTION

    instance = super().update(instance, validated_data)
    # ADD CODE HERE THAT YOU WANT TO VIEW
    return instance

yeah!! you are just cleaning the requested data by popping. But I think every time the requested data got updated

FraCata00 commented 10 months ago

the validated_data argument is the body data request in method PATCH or PUT, after validation by serializer or model

PARTHIB-DEB commented 10 months ago

the validated_data argument is the body data request in method PATCH or PUT, after validation by serializer or model

No no , I was telling that Everytime I hit get request I get the original data , so whether you previously get the data and done something with it, does it make any affect when you again hit the get request? it's my point

FraCata00 commented 10 months ago

But you pass the data in request body?

FraCata00 commented 10 months ago

Sorry bro, i'm in office work

PARTHIB-DEB commented 10 months ago

But you pass the data in request body?

yes, after validations. After all updations are one type of POST