创建用户时在 React 中管理 Django Rest Framework 500 内部服务器错误

Managing Django Rest Framework 500 Internal Server Error in React when creating user

我正在尝试我的第一个 React + DRF 项目。这是我的困难。当我尝试使用现有用户名创建用户时,出现 500 内部服务器错误,我似乎无法在 React 中捕获它或对其执行任何操作。它在其他方面工作得很好,我在检索用户信息时会显示错误(例如:“确定不存在”)。

我从后端得到的 IntegrityError 错误的完整 traceback 是:

Traceback (most recent call last):
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "users_customuser_username_key"
DETAIL:  Key (username)=(kenshiro) already exists.


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/views/generic/base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/bernardino/Desktop/boombust/users/views.py", line 33, in post
    user = serializer.save()
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/rest_framework/serializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "/Users/bernardino/Desktop/boombust/users/serializers.py", line 59, in create
    instance.save()
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/contrib/auth/base_user.py", line 68, in save
    super().save(*args, **kwargs)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 806, in save
    self.save_base(
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 857, in save_base
    updated = self._save_table(
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 1000, in _save_table
    results = self._do_insert(
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/base.py", line 1041, in _do_insert
    return manager._insert(
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/query.py", line 1434, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1621, in execute_sql
    cursor.execute(sql, params)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 103, in execute
    return super().execute(sql, params)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/bernardino/Desktop/boombust/.env/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "users_customuser_username_key"
DETAIL:  Key (username)=(kenshiro) already exists.

views.py中的视图是:

class CustomUserCreate(APIView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format='json'):
        serializer = CustomUserSerializer(data=request.data)
        
        if serializer.is_valid(raise_exception=True):
            try:
                user = serializer.save()
                if user:
                    json = serializer.data
                    return Response(json, status=status.HTTP_201_CREATED)
            except IntegrityError:
                return Response({"error": "This username is already taken."}, status=status.HTTP_406_NOT_ACCEPTABLE)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这是 React 逻辑:

const onSubmit = async (values) => {
    const user = {
      first_name: values.firstName,
      last_name: values.lastName,
      username: values.username,
      email: values.email,
      password: values.password,
    };

   const response = await fetch(`users/user/create/`, {
    method: "POST",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({...user}),
  }).catch(err => err);

  const text = await response.text();
  console.log(response.status);
  if (response.status === 201) {    
    console.log("success", JSON.parse(text));
    
  } else {
    console.log("failed", text);
  }

};

这是来自 serializers.py 的序列化程序:

class CustomUserSerializer(serializers.ModelSerializer):
    token = serializers.SerializerMethodField()
    password = serializers.CharField(write_only=True)
    email = serializers.EmailField(
        required=True
    )
    username = serializers.CharField(required=True)
    first_name = serializers.CharField(required=True)
    last_name = serializers.CharField(required=True)
    password = serializers.CharField(
        min_length=8, write_only=True, required=True)
    
    class Meta:
        model = CustomUser
        fields = ('email', 'username', 'password', 'token', 'first_name', 'last_name')
        extra_kwargs = {'password': {'write_only': True}}

    def get_token(self, user):
        refresh = RefreshToken.for_user(user)
        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        }

如果有帮助,我在 CustomUser class 中有 username = CICharField(unique=True) models.py

您需要在保存模型之前进行检查。

class CustomUserCreate(APIView):
    permission_classes = (permissions.AllowAny,)

    def post(self, request, format='json'):
        serializer = CustomUserSerializer(data=request.data)
        
        if serializer.is_valid(raise_exception=True):

            # here you can check if the username already exists or not
            username = serializer.validated_data.get('username')
            if CustomUser.objects.filter(username = username).count() > 0:
                return Response({"error": "This username is already taken."}, status=status.HTTP_406_NOT_ACCEPTABLE)

            # if username is new
            user = serializer.save()
            if user:
                json = serializer.data
                return Response(json, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)