UpdateAPIView | Django REST does not update data properly

I want to register values in a table of relations when updating data. Conversely, I want to generate an error if the value does not exist.

models.py

class CustomUser(AbstractBaseUser, PermissionsMixin):

    uuid = models.UUIDField(default=uuid.uuid4, primary_key=True,
                            editable=False)
    email = models.EmailField(_('email address'), unique=True)
    role = models.OneToOneField('Role', related_name='user',
                                blank=True, null=True,
                                on_delete=models.PROTECT)
    # ommited...

class Role(models.Model):
    slug = models.SlugField(unique=True)

    def __str__(self):
        return self.slug

serializers.py

from drf_writable_nested import WritableNestedModelSerializer
from rest_framework import serializers

from accounts.models import CustomUser, Role


class RoleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Role
        fields = ('slug',)


class UserSerializer(WritableNestedModelSerializer):
    role = RoleSerializer()

    class Meta:
        model = CustomUser
        fields = ('uuid', 'email', 'role', 'password')
        extra_kwargs = {'password': {'write_only': True, 'required': True}}

    def create(self, validated_data):
        return CustomUser.objects.create_user(**validated_data)

views.py

class UserUpdateView(generics.UpdateAPIView):
    queryset = CustomUser.objects.all()
    serializer_class = UserSerializer

Role DB Table

id:1 | slug:admin

Expectation

Request(PATCH) Parameter

{
    "role":{
        "slug":"foo"
    }
}

# error: foo does not exist in the Role table
{
    "role":{
        "slug":"admin"
    }
}

# OK!!!

What should I do?

Try to use SlugRelatedField:

class UserSerializer(WritableNestedModelSerializer):
    role = serializers.SlugRelatedField(slug_field='slug')

    class Meta:
        model = CustomUser
        fields = ('uuid', 'email', 'role', 'password')
        extra_kwargs = {'password': {'write_only': True, 'required': True}}

    def create(self, validated_data):
        return CustomUser.objects.create_user(**validated_data)

In this case request should be unnested:

{
    "role":"foo"
}
Back to Top