Django用户注册接口异常:返回邮箱已存在但用户已创建
问题描述
测试新用户注册功能时,发送POST请求后收到返回信息:
{"details": "USER WITH THIS EMAIL ALREADY EXITS!"}
但查看数据库发现新用户已成功创建。删除该用户后再次尝试,依然出现相同问题。
views.py
class MyTokenObtainPairSerializer(TokenObtainPairSerializer): def validate(self, attrs): data = super().validate(attrs) serializer = UserSerializerWithToken(self.user).data for k,v in serializer.items(): data[k]=v return data class MyTokenObtainPairView(TokenObtainPairView): serializer_class = MyTokenObtainPairSerializer @api_view(['GET']) @permission_classes([IsAuthenticated]) def getUserProfile(request): user = request.user serializer = UserSerializer(user,many=False) return Response(serializer.data) @api_view(['GET']) @permission_classes([IsAdminUser]) def getUsers(request): user = User.objects.all() serializer = UserSerializer(user,many=True) return Response(serializer.data) # Register new users @api_view(['POST']) def registerUser(request): data = request.data print(data) try: user = User.objects.create( first_name = data['name'], username = data['email'], email = data['email'], password = make_password(data['password']), ) serializer = UserSerializerWithToken(user, many=False) return Response(serializer.data) except: message = {'details': 'USER WITH THIS EMAIL ALREADY EXITS!'} return Response(message, status=status.HTTP_400_BAD_REQUEST)
serializer.py
class UserSerializer(serializers.ModelSerializer): name = serializers.SerializerMethodField(read_only=True) _id = serializers.SerializerMethodField(read_only=True) isAdmin = serializers.SerializerMethodField(read_only=True) class Meta: model = User fields = ['id', '_id', 'username', 'email', 'name', 'isAdmin'] def get_name(self, obj): name = obj.first_name if name == "": name = obj.email return name def get__id(self, obj): return obj.id def get_isAdmin(self, obj): return obj.is_staff class UserSerializerWithToken(serializers.ModelSerializer): token = serializers.SerializerMethodField(read_only=True) class Meta: model = User fields = ['id', '_id', 'username', 'email', 'name', 'isAdmin', 'token'] def get_token(self, obj): token = RefreshToken.for_user(obj) return str(token.access_token)
urls.py
from django.urls import path from app import views from rest_framework_simplejwt.views import ( TokenObtainPairView, ) urlpatterns = [ path('', views.getRoutes, name="get-routes"), path('users/register/', views.registerUser, name="register"), path('users/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('products/', views.getProducts, name="get-products"), path('products/<str:pk>', views.getProduct, name="get-product"), path('user/profile/', views.getUserProfile, name="get-user-profile"), path('users/', views.getUsers, name="get-users"), ]
models.py
from django.db import models from django.contrib.auth.models import User class Product(models.Model): user=models.ForeignKey(User,on_delete=models.SET_NULL,null=True) name=models.CharField(max_length=200,null=True,blank=True) image=models.ImageField(null=True,blank=True) brand=models.CharField(max_length=200,null=True,blank=True) category=models.CharField(max_length=200,null=True,blank=True) description=models.TextField(null=True,blank=True) rating=models.DecimalField(max_digits=7,decimal_places=2,null=True,blank=True) numReviews=models.IntegerField(null=True,blank=True,default=0) price=models.DecimalField(max_digits=7,decimal_places=2,null=True,blank=True) countInStock=models.IntegerField(null=True,blank=True,default=0) created=models.DateTimeField(auto_now_add=True) _id=models.AutoField(primary_key=True,editable=False) def __str__(self): return self.name
问题原因及修复方案
核心问题1:序列化时缺少RefreshToken导入
serializer.py中UserSerializerWithToken的get_token方法使用了RefreshToken但未导入该类,导致创建用户后序列化阶段抛出NameError异常,触发registerUser的except块返回错误信息,但此时用户已经成功写入数据库。
核心问题2:异常捕获范围过大
registerUser的except块捕获所有异常,不管是用户名重复的IntegrityError还是其他错误,都返回"邮箱已存在"的错误,误导排查方向。
修复步骤:
在serializer.py中导入RefreshToken
在文件顶部添加导入语句:from rest_framework_simplejwt.tokens import RefreshToken缩小异常捕获范围,精准处理重复用户错误
修改registerUser的异常逻辑,只捕获用户名重复的IntegrityError,并区分其他异常:from django.db import IntegrityError # 需导入该类 @api_view(['POST']) def registerUser(request): data = request.data print(data) try: user = User.objects.create( first_name = data['name'], username = data['email'], email = data['email'], password = make_password(data['password']), ) serializer = UserSerializerWithToken(user, many=False) return Response(serializer.data) except IntegrityError: message = {'details': 'USER WITH THIS EMAIL ALREADY EXITS!'} return Response(message, status=status.HTTP_400_BAD_REQUEST) except Exception as e: message = {'details': f'注册失败:{str(e)}'} return Response(message, status=status.HTTP_400_BAD_REQUEST)可选:为User模型的email字段添加唯一约束
默认Django的User模型email字段不唯一,若需确保邮箱唯一,可自定义User模型,或通过迁移为email字段添加唯一约束,避免同一邮箱多次注册。
内容的提问来源于stack exchange,提问作者Khaled
相关产品推荐
相关产品推荐

