Django Rest Framework - serializer code not executing

413 Views Asked by At

I am trying to implement a user registration with password hashing.

The problem is that the password is saved raw (as it was typed).

For some reason, I think the create method in the serializer is not called.

Doesn't matter if I comment the method out or not comment it out, and try to register, same result - is saves the user to the database without hashing the password. It means that the code doesn't execute?

Views.py

class UserViewSet(mixins.CreateModelMixin,
               mixins.RetrieveModelMixin,
               mixins.ListModelMixin,
               viewsets.GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsCreationOrIsAuthenticated,)

Serizliers.py

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'password', )
        extra_kwargs = {'password': {'write_only': True}}

        def create(self, validated_data):
            user = User(
                first_name=validated_data['first_name'],
                username=validated_data['username'],
                last_name=validated_data['last_name']
            )
            user.set_password(validated_data['password'])
            user.save()
            return user

I have been struggling with this for a while - can't has the password.

Any ideas?

2

There are 2 best solutions below

1
On

Instead of writing your create method in serializers.py, do this work by overriding the perform_create() method in your views.py. To do some extra work on creation of an object, DRF provides this hook. This will make the code more clean and DRY.

As per the DRF docs,

Save and deletion hooks:

The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.

perform_create(self, serializer) - Called by CreateModelMixin when saving a new object instance.
perform_update(self, serializer) - Called by UpdateModelMixin when saving an existing object instance.
perform_destroy(self, instance) - Called by DestroyModelMixin when deleting an object instance.
These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data.

You can do that by:

views.py

def perform_create(self, serializer):
    user = User(
            first_name=serializer.data['first_name'],
            username=serializer.data['username'],
            last_name=serializer.data['last_name']
        )
    user.set_password(serializer.data['password'])
    user.save()
0
On

The create function is within the target class, it must be inside the main class, remove an indentation tab

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'password', )
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User(
            first_name=validated_data['first_name'],
            username=validated_data['username'],
            last_name=validated_data['last_name']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user