How to use CustomUser
with dj_rest_auth
to register with email
and password
.
I have the source code below, but the username
information is required during the sign-up process.
I would like to know how to sign up with only the emai
l, password1
, and password2
information.
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts',
'rest_framework',
'dj_rest_auth',
'dj_rest_auth.registration',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_framework.authtoken'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'allauth.account.middleware.AccountMiddleware'
]
SITE_ID = 1
AUTH_USER_MODEL = 'accounts.CustomUser'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_SIGNUP_FIELDS = ['email', 'password1', 'password2']
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'none'
REST_AUTH_REGISTER_SERIALIZERS = {
'REGISTER_SERIALIZER': 'accounts.serializers.CustomRegisterSerializer',
}
accounts/models.py
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.db import models
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('The Email field must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
accounts/serializers .py
from dj_rest_auth.registration.serializers import RegisterSerializer
class CustomRegisterSerializer(RegisterSerializer):
def get_cleaned_data(self):
return {
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'password2': self.validated_data.get('password2', ''),
}
project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('auth/', include('dj_rest_auth.urls')),
path('auth/registration/', include('dj_rest_auth.registration.urls')),
]
UPDATED:
accounts/serializers .py
from django.contrib.auth import get_user_model
from rest_framework import serializers
from allauth.account.adapter import get_adapter
from allauth.account.utils import setup_user_email
User = get_user_model()
class CustomRegisterSerializer(serializers.Serializer):
username = None
email = serializers.EmailField(required=True)
password1 = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError("The two password fields didn't match.")
return data
def get_cleaned_data(self):
return {
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'password2': self.validated_data.get('password2', ''),
}
def custom_signup(self, request, user):
pass
def save(self, request):
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
user.email = self.cleaned_data['email']
user.set_password(self.cleaned_data['password1'])
user.save()
self.custom_signup(request, user)
setup_user_email(request, user, [])
return user
Django 4.2
dj-rest-auth 7.0.1
django-allauth 65.9.0
djangorestframework 3.16.0
It seems to me that the base class you are inheriting your serializer from is expecting a username. You could try removing the username via username=None.
Then the code would look like this:
class CustomRegisterSerializer(RegisterSerializer):
username = None # <- remove field
def get_cleaned_data(self):
return {
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
'password2': self.validated_data.get('password2', ''),
}
UPDATED
Ok, considering that the previous answer didn't help.
This is what I did and it works:
I left the model unchanged.
Serializer:
from rest_framework import serializers
from django.contrib.auth import get_user_model
User = get_user_model()
class RegisterSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True, style={'input_type': 'password'})
password2 = serializers.CharField(write_only=True, style={'input_type': 'password'})
class Meta:
model = User
fields = ['email', 'password1', 'password2']
def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError("Passwords do not match.")
return data
def create(self, validated_data):
email = validated_data['email']
password = validated_data['password1']
user = User.objects.create_user(email=email, password=password)
return user
Views:
from rest_framework import status
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import CustomUser
from .serializers import RegisterSerializer
class RegisterView(APIView):
def post(self, request):
serializer = RegisterSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'detail': 'User created successfully'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls:
path('register/', RegisterView.as_view(), name='register'),
Settings:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts.apps.AccountsConfig',
]
...
AUTH_USER_MODEL = 'accounts.CustomUser'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_SIGNUP_FIELDS = ['email', 'password1', 'password2']
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'none'
You send a POST request to 127.0.0.1:8000/register/
with a request body of type:
{
"email": "test11@example.com",
"password1": "supersecretpassword",
"password2": "supersecretpassword"
}
and the user is successfully created in the database. @Tio