Django报错:BaseSerializer.is_valid()仅接受1个参数却传入2个
本地无法创建用户的问题修复
此前项目运行正常,因Heroku取消免费套餐,尝试迁移到其他平台后,本地突然无法创建用户,触发错误。相关代码如下:
序列化器代码(serializers/common.py)
from xml.dom import ValidationErr from rest_framework import serializers from django.contrib.auth import get_user_model, password_validation from django.contrib.auth.hashers import make_password User = get_user_model() class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) confirm_password = serializers.CharField(write_only=True) def validate(self, data): password = data.pop('password') confirm_password = data.pop('confirm_password') if password != confirm_password: raise ValidationErr({ 'confirm_password': 'Does not match the password'}) password_validation.validate_password(password) data['password'] = make_password(password) return data class Meta: model = User fields = ('id', 'username', 'email', 'password', 'confirm_password')
视图代码(views.py)
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.exceptions import PermissionDenied from django.contrib.auth import get_user_model import jwt User = get_user_model() from datetime import datetime, timedelta from jwt_auth.serializers.common import UserSerializer from django.conf import settings class RegisterView(APIView): def post (self, request): create_user = UserSerializer(data=request.data) try: create_user.is_valid(True) create_user.save() return Response(create_user.data, status=status.HTTP_201_CREATED) except Exception as e: print(str(e)) return Response(e.__dict__ if e.__dict__ else str(e), status=status.HTTP_422_UNPROCESSABLE_ENTITY) class LoginView(APIView): def post(self, request): password = request.data.get('password') username = request.data.get('username') try: user_login = User.objects.get(username=username) except User.DoesNotExist: raise PermissionDenied('Credentials are incorrect!') if not user_login.check_password(password): raise PermissionDenied('Credentials are incorrect!') dt = datetime.now() + timedelta(days=7) token = jwt.encode( { 'sub': user_login.id, 'exp': int(dt.strftime('%s')) }, settings.SECRET_KEY, 'HS256' ) print('TOKEN ----->', token) return Response({ 'token': token, 'message': f'Welcome back {user_login.username}' })
问题排查与修复方案
1. 异常类导入错误
当前导入的xml.dom.ValidationErr是XML解析专用异常,并非Django REST Framework序列化器应使用的异常类。替换为DRF自带的异常:
# 替换原导入语句 from rest_framework.exceptions import ValidationError
同时将validate方法内的raise ValidationErr改为raise ValidationError。
2. Python缩进错误
Python依赖缩进区分代码块,你的代码多处缩进缺失,直接导致语法或逻辑错误,需修正:
validate方法中,if判断后的raise语句需缩进4个空格RegisterView.post的try块内所有代码、except块内代码需缩进LoginView.post的try、except、if块内代码,以及jwt.encode的字典内容需正确缩进
示例修复后的validate方法:
def validate(self, data): password = data.pop('password') confirm_password = data.pop('confirm_password') if password != confirm_password: raise ValidationError({ 'confirm_password': '密码不匹配'}) password_validation.validate_password(password) data['password'] = make_password(password) return data
3. 视图方法参数优化(可选)
create_user.is_valid(True)虽能触发异常,但更清晰的写法是create_user.is_valid(raise_exception=True),提升代码可读性。
4. JWT时区问题(可选)
datetime.now()使用本地时间,可能导致JWT过期时间计算偏差,建议替换为UTC时间:
dt = datetime.utcnow() + timedelta(days=7)
完成以上修复后,重启本地服务即可正常创建用户。
内容的提问来源于stack exchange,提问作者rokster
相关产品推荐
相关产品推荐

