1
votes

I switched to a custom user manager to use email as a username. Since making that change, all fields aside from email and password are not being populated on register, eg, a user is created but has no first_name, last_name, etc. I was under the impression django classes could be overridden on a field fo field basis without disrupting other fields. Is that not the case?

Manager:

class CustomUserManager(BaseUserManager):
    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """
def create_user(self, email, password, **extra_fields):
    """
    Create and save a User with the given email and password.
    """
    if not email:
        raise ValueError(_('The Email must be set'))
    email = self.normalize_email(email)
    user = self.model(email=email, **extra_fields)
    user.set_password(password)
    user.save()
    return user

def create_superuser(self, email, password, **extra_fields):
    """
    Create and save a SuperUser with the given email and password.
    """
    extra_fields.setdefault('is_staff', True)
    extra_fields.setdefault('is_superuser', True)
    extra_fields.setdefault('is_active', True)

    if extra_fields.get('is_staff') is not True:
        raise ValueError(_('Superuser must have is_staff=True.'))
    if extra_fields.get('is_superuser') is not True:
        raise ValueError(_('Superuser must have is_superuser=True.'))
    return self.create_user(email, password, **extra_fields)

Serializer:

class RegisterSerializer(serializers.ModelSerializer):

class Meta:
    User = get_user_model()
    model = User
    fields = ('first_name', 'last_name', 'email', 'password', 'startTime', 'groups')
    extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        request = self.context["request"]
        if (request.data.get("groups", None) == 1):
            is_staff = True
        else:
            is_staff = False
        user = User.objects.create_user(validated_data['first_name'],
                                        validated_data['last_name'],
                                        validated_data['email'],
                                        validated_data['password'],
                                        validated_data['startTime'],
                                        validated_data['groups'],
                                        validated_data['is_staff'])
        return user

Model:

class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []

startTime = models.TimeField(null=True)
# add additional fields in here
objects = CustomUserManager()
def __str__(self):
    return self.email

View:

class RegisterAPI(generics.GenericAPIView):
  permission_classes = [
    permissions.IsAdminUser
  ]
  serializer_class = RegisterSerializer

  def post(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = serializer.save()
    return Response({
      "user": UsersSerializer(user, context=self.get_serializer_context()).data,
      #"token": AuthToken.objects.create(user)
    })
1

1 Answers

1
votes

You need to populate these through named parameters, not positional ones:

user = User.objects.create_user(
    first_name=validated_data['first_name'],
    last_name=validated_data['last_name'],
    email=validated_data['email'],
    password=validated_data['password'],
    startTime=validated_data['startTime'],
    groups=validated_data['groups'],
    is_staff=is_staff
)

or through dictionary unpacking:

user = User.objects.create_user(
    **validated_data,
    is_staff=is_staff
)