首页 > 解决方案 > 为什么通过 django rest 框架注册用户时出现状态码错误

问题描述

我正在开发一个通过 Django restframework 进行用户注册的身份验证系统。我已经按照youtube链接来配置序列化器。由于导师没有使用基于类的视图,所以,我没有遵循那部分。我已经为ListCreateAPIView.

序列化程序.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 save(self, **kwargs):
        """
        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.
        """
        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'],
        )

        password = self.validated_data['password']
        password2 = self.validated_data['password2']

        if password != password2:
            raise serializers.ValidationError({'password': f'password must match..'})
        account.set_password(password)
        account.save()
        return account

视图.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)

注意:我正在使用自定义用户模型

模型.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)

APP.urls.py

from django.urls import path
from .views import signupView, UserRegisterView


urlpatterns = [
    path('signup/', signupView, name='signup'),
    path('register/', UserRegisterView.as_view(), name='register'),
    ]

项目.urls.py

from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('/api/accounts/', include('drf_registration.urls')),
    path('apii/', include('AUTHENTICATION.urls')),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

当我在 POSTMAN for POST 方法中测试 API 时,出现以下错误:

{
    "status": "error"
}

邮递员网址:localhost:8000/apii/register/

我附上了截图供参考在此处输入图像描述

卷曲输出

curl --location --request POST 'localhost:8000/apii/register/' \
--header 'Content-Type: application/json' \
--header 'Cookie: csrftoken=rMmU3sp2Z75ijK47MY3ajwmGqr9J0qm3SQu4iDvAf1e54nibybpZMPNQsBoFpDua' \
--form 'email="test.test@yahoo.com"' \
--form 'first name="Ami"' \
--form 'last name="Sah"' \
--form 'employee code="00060"' \
--form 'contact="7507973333"' \
--form 'password="123456"' \
--form 'password2="123456"'

标签: djangodjango-rest-framework

解决方案


一些修正,

  1. 将序列化程序验证部分移至 validate 方法。
  2. 视图中的 serializer_class 必须是类而不是序列化程序实例。将其更改为 serializer_class = RegistrationSerializers。
  3. 不要使用 if 分支 serializer.is_valid(),而是将其更改为 serializer.is_valid(raise_exception=True) # 用于调试。您将了解哪些字段有错误。或者您可以在调用 serializer.is_valid() 之后记录 serializer.errors。
  4. 覆盖 ModelSerializer.create 而不是 ModelSerializer.save。它更适合这个目的。
  5. 我不明白在后端进行密码双重检查验证的意义。只需让前端处理它。

推荐阅读