djangodjango-rest-frameworkdjango-allauthdjango-rest-auth

Django rest-auth allauth registration with email, first and last name, and without username


I am using django-rest-auth and allauth for login and registration in my django app. I haven't written any extra single line of code of my own for login or registration. Registration is successful with emailid and provided password.

I am not using username for authentication, instead email.

In my browsable api for registration I get following:

enter image description here

Along with these fields I want to have first_name and last_name (the default auth_user table had these columns) so that my newly created auth_user also has these fields set along with email and hashed password.

How can I achieve this? This browsable form itself is not so important but being able to store first_name and last_name is what I need primarily.


Solution

    1. Make sure you have ACCOUNT_USERNAME_REQUIRED = False in your settings.py file.

    2. For first_name and last_name you need to write a custom RegisterSerializer (https://github.com/iMerica/dj-rest-auth/blob/bf168d9830ca2e6fde56f83f46fe48ab0adc8877/dj_rest_auth/registration/serializers.py#L197)

    here's a sample code for serializers.py

    from allauth.account import app_settings as allauth_settings
    from allauth.utils import email_address_exists
    from allauth.account.adapter import get_adapter
    from allauth.account.utils import setup_user_email
    
    class RegisterSerializer(serializers.Serializer):
        first_name = serializers.CharField(required=True, write_only=True)
        last_name = serializers.CharField(required=True, write_only=True)
        email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
        password1 = serializers.CharField(write_only=True)
        password2 = serializers.CharField(write_only=True)
    
        def validate_username(self, username):
            username = get_adapter().clean_username(username)
            return username
    
        def validate_email(self, email):
            email = get_adapter().clean_email(email)
            if allauth_settings.UNIQUE_EMAIL:
                if email and email_address_exists(email):
                    raise serializers.ValidationError(
                        _('A user is already registered with this e-mail address.'),
                    )
            return email
    
        def validate_password1(self, password):
            return get_adapter().clean_password(password)
    
        def validate(self, data):
            if data['password1'] != data['password2']:
                raise serializers.ValidationError(_("The two password fields didn't match."))
            return data
    
        def custom_signup(self, request, user):
            pass
    
        def get_cleaned_data(self):
            return {
                'first_name': self.validated_data.get('first_name', ''),
                'last_name': self.validated_data.get('last_name', ''),
                'username': self.validated_data.get('username', ''),
                'password1': self.validated_data.get('password1', ''),
                'email': self.validated_data.get('email', ''),
            }
    
        def save(self, request):
            adapter = get_adapter()
            user = adapter.new_user(request)
            self.cleaned_data = self.get_cleaned_data()
            user = adapter.save_user(request, user, self, commit=False)
            if "password1" in self.cleaned_data:
                try:
                    adapter.clean_password(self.cleaned_data['password1'], user=user)
                except DjangoValidationError as exc:
                    raise serializers.ValidationError(
                        detail=serializers.as_serializer_error(exc)
                )
            user.save()
            self.custom_signup(request, user)
            setup_user_email(request, user, [])
            return user
    
    1. In settings.py make sure you add to refer to new Serializer.

      REST_AUTH_REGISTER_SERIALIZERS = {
              'REGISTER_SERIALIZER': 'path.to.RegisterSerializer',
      }