You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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还是其他错误,都返回"邮箱已存在"的错误,误导排查方向。


修复步骤:

  1. 在serializer.py中导入RefreshToken
    在文件顶部添加导入语句:

    from rest_framework_simplejwt.tokens import RefreshToken
    
  2. 缩小异常捕获范围,精准处理重复用户错误
    修改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)
    
  3. 可选:为User模型的email字段添加唯一约束
    默认Django的User模型email字段不唯一,若需确保邮箱唯一,可自定义User模型,或通过迁移为email字段添加唯一约束,避免同一邮箱多次注册。

内容的提问来源于stack exchange,提问作者Khaled

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 23:01:52