1
votes

I am trying to create an endpoint for creating a new user. If I put a create method in the serializer will perform_create still be called on my ApiView? It seems User.objects.create is still being called because if I pass 'confirm-password' in the serializer I get an error:

Got a TypeError when calling User.objects.create(). This may be because you have a writable field on the serializer class that is not a valid argument to User.objects.create(). You may need to make the field read-only, or override the UserSerializer.create() method to handle this correctly. Original exception text was: 'confirm_password' is an invalid keyword argument for this function.

Why is User.objects.create() being called when I'm using .create_user() in the serializer create method? This is also causing is_active to default to true even though I'm setting it to false in the serializer.

class UserCreateSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False)
    confirm_password = serializers.CharField(write_only=True, required=False)

    class Meta:
        model = get_user_model()
        fields = ('id', 'email', 'username',
              'first_name', 'last_name', 'password',
              )
        read_only_fields = ('date_joined')

    def validate_email(self, value):

        if value and User.objects.filter(email=value).count():
            raise serializers.ValidationError(u'Email addresses is already registered.')
        return value

    def create(self, validated_data):
        user = get_user_model().objects.create_user(
            username=validated_data['username'],
            email=validated_data['email'],
            password=validated_data['password'],
            is_active=False)
        return user


class UserCreateApiView(generics.CreateAPIView):
    serializer_class = UserSerializer
    permission_classes = [AllowAny,]
    queryset = get_user_model().objects.all()
1

1 Answers

0
votes

According to the docs, User.objects.create_user() will always result in a user where is_active is True.

create_user(username, email=None, password=None, **extra_fields)

Creates, saves and returns a User.

The username and password are set as given. The domain portion of email is automatically converted to lowercase, and the returned User object will have is_active set to True.

If no password is provided, set_unusable_password() will be called.

The extra_fields keyword arguments are passed through to the User’s __init__ method to allow setting arbitrary fields on a custom User model.

Here's a possible workaround:

def create(self, validated_data):
    user = get_user_model().objects.create_user(
        username=validated_data['username'],
        email=validated_data['email'],
        password=validated_data['password'])

    user.is_active = False
    user.save()
    return user