I am developing an authentication system for User registration through Django rest framework.
serializers.py
from rest_framework import serializers
from .models import NewEmployeeProfile
class RegistrationSerializers(serializers.ModelSerializer):
'''
We need to add the password2, as its not the part of the NewEmployeeProfile model. So, we need to make it manually.
'''
password2 = serializers.CharField(style={'input_type: password'}, write_only=True)
class Meta:
model = NewEmployeeProfile
fields = ('email', 'first_name', 'last_name', 'employee_code', 'contact', 'dob', 'password', 'password2')
extra_kwargs = {
'password': {'write_only': True}
}
def create(self, validated_data):
"""
before we save the new user, we need to make sure that the password1, and password2 matches. In order to do
that, we need to override the save() method.
"""
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': f'password must match..'})
return NewEmployeeProfile.objects.create(**validated_data)
def validate(self, attrs):
if attrs:
account = NewEmployeeProfile(
email=self.validated_data['email'],
first_name=self.validated_data['first name'],
last_name=self.validated_data['last name'],
employee_code=self.validated_data['employee code'],
contact=self.validated_data['contact'],
dob=self.validated_data['dob'],
)
account.save()
return account
views.py
class UserRegisterView(ListCreateAPIView):
create_queryset = NewEmployeeProfile.objects.all()
serializer_class = RegistrationSerializers(create_queryset, many=True)
permission_classes = [AllowAny]
def post(self, request, *args, **kwargs):
serializer = RegistrationSerializers(data=request.data)
if serializer.is_valid():
newUser = serializer.save()
serializer = RegistrationSerializers(newUser)
return Response(data={"status": "OK", "message": serializer.data}, status=status.HTTP_201_CREATED)
return Response(data={"status": "error"}, status=status.HTTP_400_BAD_REQUEST)
models.py
from django.db import models
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, AbstractUser
from django.utils.translation import gettext_lazy as _
class AccountManager(BaseUserManager):
def create_superuser(self, email, password, **extra_fields):
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)
def create_user(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
if not email:
raise ValueError(_('Enter the email before proceeding'))
email = self.normalize_email(email)
user = self.model(email=email, password=password, **extra_fields)
user.set_password(password)
user.save()
return user
class NewEmployeeProfile(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
employee_code = models.CharField(max_length=10, null=True)
contact = models.CharField(max_length=10, null=True)
dob = models.DateField(blank=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'contact']
def __str__(self):
return str(self.email)
The problem is when I test the API in postman, it gives below output:
{
"first_name": [
"This field is required."
],
"last_name": [
"This field is required."
]
}
However, while testing POST method in POSTMAN, I have entered all data.
screenshot:
while troubleshooting I found that in serializers.py inside the "create" function I returned nothing. So, I added
return NewEmployeeProfile.objects.create(**validated_data)
Now when I test my API, the POST submition goes in to infinite loop, giving no output in the POSTMAN 'body'.
I guess, I haven't overridden the "create" and "validate" methods properly.
app.urls
from django.urls import path
from .views import signupView, UserRegisterView
urlpatterns = [
path('signup/', signupView, name='signup'),
path('register/', UserRegisterView.as_view(), name='register'),
]
project.url
urlpatterns = [
path('admin/', admin.site.urls),
path('apii/', include('AUTHENTICATION.urls')),
]
new error:
Bad Request: /apii/register/
[05/Apr/2021 11:17:48] "POST /apii/register/ HTTP/1.1" 400 82
I think issue is with the keys you sent in request in the postman
I believe it should be first_name
and last_name
instead of first name
and last name
respectively.