How to allow blank password via django-rest-api user create

1k Views Asked by At

In my case, I need to have one user group which email and password will not be set on user creation. They will not require to auth themselves either.

I managed to do custom user with a nullable email, but I cannot find a way to allow blank password in API call or Django admin forms. I do not really care much about forms, but I need to have it working via API.

How could I allow to create a new custom user with a blank password and maybe set it to something meaningful if it comes blank (like set_unusable_password())?

Thanks!

My CustomUserManager:

from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _


class CustomUserManager(BaseUserManager):
    def create_user(self, email, password, **extra_fields):

        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        # if password == "":
        #     user.set_password(None)
        # else:
        user.set_password(password)
        user.save()
        return user

    def create_superuser(...
2

There are 2 best solutions below

4
On

You can base your CustomUser on AbstractUser and use set_password

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
...

Thanks to that, you have access to the function set_password. Any user based on CustomUser will inherit :

def set_password(self, raw_password):
    self.password = make_password(raw_password)
    self._password = raw_password

And if you look closely make_password you will realize it possible to give it None :

 if password is None:
    return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)

You could check the full example on Django to have a starting point with a Manager

Your model will look like :

class MyUser(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

UPDATE after you upload your Manager :

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):

        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(...

You forgot the password=None in your create_user. That is why you have this error required.

0
On

This helped me: how to mention password field in serializer?

I have declared password field in user serializer and set required=False

class CustomUserSerializer(serializers.ModelSerializer):

    password = serializers.CharField(
        write_only=True,
        required=False,
    )

    class Meta:
        model = CustomUser
        fields = ("id", "email", "password")

    def create(self, validated_data):
        validated_data['password'] = make_password(validated_data.get('password'))
        user = CustomUser.objects.create_user(**validated_data)
        Token.objects.create(user=user)

        return user