django.db.utils.IntegrityError: UNIQUE constraint failed: authtoken_token.user_id

django.db.utils.IntegrityError: UNIQUE constraint failed: authtoken_token.user_id

我是 Django 休息框架的新手,我正在尝试使用 Token 为我的 API 进行单元测试,但它一直抛出 IntegrityError。我研究了很多博客以找到解决方案但找不到。请帮我解决这个问题。提前致谢。

这是我试过的代码

from django.contrib.auth.models import User
from rest_framework.test import APITestCase, APIRequestFactory, force_authenticate
from rest_framework.authtoken.models import Token

from myapp.api.views import UserViewSet


class UserTestCase(APITestCase):
    def setUp(self):
        self.superuser = User.objects.create_user(username='superuser', email='uid.sawyer@gmail.com',
                                                  password='superuser',
                                                  is_staff=True)
        self.factory = APIRequestFactory()

        self.token = Token.objects.create(user=self.superuser)
        self.token.save()

    def test_list(self):
        request = self.factory.get('/api/users/')
        force_authenticate(request, user=self.superuser, token=self.token)
        response = UserViewSet.as_view({'get': 'list'})(request)
        self.assertEqual(response.status_code, 200)

终于,我明白了。我没有注意到我在信号中创建了令牌,其中创建了每个用户创建令牌。谢谢@Willem Van Onsem

唯一约束失败:authtoken_token.user_id 出现此错误是因为数据库中已存在该用户的令牌。因此,当它尝试使用相同的 user_id 创建新令牌时,它会给出一个错误

如果您查看用户的管理员令牌已经存在

引用自https://excellencetechnologies.in/blog/django-rest-api-authentication-part5/:

做一个try-except函数:


class UserAuth(APIView):

   # Manager User Login and other things
    

    def post(self, request):
        
        # login
       
        user = authenticate(
            username=request.data.get("username"),
            password=request.data.get("password")
            )
        if user is not None:
            # A backend authenticated the credentials

            try:
                token = Token.objects.get(user_id=user.id)

            except Token.DoesNotExist:
                token = Token.objects.create(user=user)

            return Response(token.key)

        else:
            # No backend authenticated the credentials
            return Response([], status=status.HTTP_401_UNAUTHORIZED)