为啥通过 django rest 框架注册用户时出现状态码错误

Posted

技术标签:

【中文标题】为啥通过 django rest 框架注册用户时出现状态码错误【英文标题】:why am I getting status code error while registering user through django rest framework为什么通过 django rest 框架注册用户时出现状态码错误 【发布时间】:2021-06-30 17:12:57 【问题描述】:

我正在开发一个通过 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

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)

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'),
    ]

project.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"'

【问题讨论】:

【参考方案1】:

一些更正,

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

【讨论】:

我听从了你的建议,我在 POSTMAN 中看到的输出有些不同。但我仍然有一些分歧。为此,我将单独打开另一个线程。不过感谢您的帮助。 在原帖中将邮递员添加为 curl

以上是关于为啥通过 django rest 框架注册用户时出现状态码错误的主要内容,如果未能解决你的问题,请参考以下文章

Django Social登录/注册使用rest框架

安全用户注册 django rest 端点

登录到数据库时,Django rest框架不加密密码

注册过程中dJango rest api中的ConnectionRefusedError

使用 django-allauth 和 django-rest 框架

如何修复在 Django Rest Framework 中使用 REST API 登录时出现的 CSRF 错误?