BigZ
BigZ

Reputation: 886

DRF serializer update nested user

i'm using Django 1.11 and the Django Rest Framework in order to create an API, where a user can create and update an employee which is related to the django user model.
The stripped down code i've got looks like this:

I've got this model:

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee')
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

these two viewsets:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.UserSerializer
    permission_classes = [permissions.IsAuthenticated]

and

class EmployeeViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.EmployeeSerializer
    permission_classes = [permissions.IsAuthenticated]

and these two serializers:

class UserSerializer(serializers.HyperlinkedModelSerializer)
    class Meta
        models = User
        fields = ('url', 'id', 'username', 'email', 'is_staff', 'first_name', 'last_name', 'password')
        read_only_field = ('id',)

    def validate(self, data)
        # ... Check if data is valid and if so...
        return data

and

class EmplyoeeSerializer(serializers.HyperlinkedModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Employee
        field = ('url', 'uuid', 'user')
        read_only_field = ('uuid')

    def validate(self, data):
        return data

    def create(self, validated_data):
        user = User(**validated_data['user'])
        user.save()
        employee = Employee(user=user)
        employee.save()
        return employee

    def update(self, employee, user):
        employee.user.username = user.username
        employee.user.email = user.email
        employee.user.first_name = user.first_name
        employee.user.last_name = user.last_name
        employee.user.is_staff = user.is_staff
        # ... Check if password has changed, and if so...
        employee.user.set_password(user.password)
        employee.user.save()
        employee.save()
        return employee

also i've got these two routers in my urls.py

router = routers.DefaultRouter()
router.register(r'api/user', views.UserViewSet, base_name='user')
router.register(r'api/employee', views.UserViewSet, base_name='employee')

Creating and updating an instance of user is no problem.
I can also create an employee which in return will create an user and then an employee assigend to that user.
I can even update the username of the employee and the user will get updated too,
but i can't update first_name, last_name, email, is_staff and password.
DRF keeps telling me that the username is already taken, but when i change the username and other information like first_name and last_name and then send a PUT request to the server, the employee and associated user instance are getting updated properly.
What am i missing?
Why can't i update the employees user instance like i can update the normal user instance when i'm at the user api endpoint? :/

Thanks in advance,
any help would be appreciated.

Upvotes: 3

Views: 720

Answers (1)

BigZ
BigZ

Reputation: 886

Finally i found out what i was missing.
The UserSerializers adds django.contrib.auth.validators.UnicodeUsernameValidator and UniqueValidator to the field username which gets checked every time i do a put request.
Adding validators = [] to the Meta Class of UserSerializer solved my problem.

Upvotes: 0

Related Questions