首页 > 解决方案 > UNIQUE 约束失败:authtoken_token.user_id 使用 Django 框架执行登录时

问题描述

尝试使用 DRF API 登录时出现以下错误**

IntegrityError at /api/auth/login
UNIQUE constraint failed: authtoken_token.user_id
Request Method: POST
Request URL:    http://127.0.0.1:8000/api/auth/login
Django Version: 2.2.16
Exception Type: IntegrityError
Exception Value:    
UNIQUE constraint failed: authtoken_token.user_id
Exception Location: D:\Django\venv\lib\site-packages\django\db\backends\sqlite3\base.py in execute, line 383
Python Executable:  D:\Django\venv\Scripts\python.exe
Python Version: 3.8.2
Python Path:    
['D:\\Django\\UserAPI',
 'c:\\program files\\python38\\python38.zip',
 'c:\\program files\\python38\\DLLs',
 'c:\\program files\\python38\\lib',
 'c:\\program files\\python38',
 'D:\\Django\\venv',
 'D:\\Django\\venv\\lib\\site-packages']
Server time:    Tue, 12 Jan 2021 19:12:18 +0000


UNIQUE constraint failed: authtoken_token.user_id while performing login using Django Framework

serializer.py

from django.contrib.auth import get_user_model
from rest_framework.authtoken.models import Token
from rest_framework import serializers
from django.contrib.auth.models import BaseUserManager,AbstractBaseUser

User = get_user_model()


class UserLoginSerializer(serializers.Serializer):
    username = serializers.CharField(max_length=8, required=True)
    password = serializers.CharField(max_length=6,required=True, write_only=True)


class AuthUserSerializer(serializers.ModelSerializer):
    auth_token = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id','username', 'password', 'email', 'mobileno','auth_token')


    def get_auth_token(self, obj):
        token = Token.objects.create(user=obj)
        return token.key


class EmptySerializer(serializers.Serializer):
    pass


class UserRegisterSerializer(serializers.ModelSerializer):
    """
    A user serializer for registering the user
    """

    class Meta:
        model = User
        fields = ('id','username', 'password','email','mobileno')

    def validate_username(self, value):
        user = User.objects.filter(username='username')
        if user:
            raise serializers.ValidationError("Username is already taken")
        return AbstractBaseUser.normalize_username(value)

views.py

from django.contrib.auth import get_user_model,logout
from django.core.exceptions import ImproperlyConfigured
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from .import serializers
from .utils import get_and_authenticate_user,create_user_account

User = get_user_model()

class AuthViewSet(viewsets.GenericViewSet):
    permission_classes = [AllowAny, ]
    serializer_class = serializers.EmptySerializer
    serializer_classes = {
        'login': serializers.UserLoginSerializer,
        'register': serializers.UserRegisterSerializer
    }

    @action(methods=['POST', ], detail=False)
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = get_and_authenticate_user(**serializer.validated_data)
        data = serializers.AuthUserSerializer(user).data
        return Response(data=user, status=status.HTTP_200_OK)

    @action(methods=['POST', ], detail=False)
    def register(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = create_user_account(**serializer.validated_data)
        data = serializers.AuthUserSerializer(user).data
        return Response(data=data, status=status.HTTP_201_CREATED)

    @action(methods=['POST', ], detail=False)
    def logout(self, request):
        logout(request)
        data = {'success': 'Sucessfully logged out'}
        return Response(data=data, status=status.HTTP_200_OK)

    def get_serializer_class(self):
        if not isinstance(self.serializer_classes, dict):
            raise ImproperlyConfigured("serializer_classes should be a dict mapping.")

        if self.action in self.serializer_classes.keys():
            return self.serializer_classes[self.action]
        return super().get_serializer_class()

标签: pythonpython-3.xdjangounit-testingdjango-rest-framework

解决方案


当您登录 >= 2 次时会出现此错误。

快速解决:

def get_auth_token(self, obj):
        token = Token.objects.get_or_create(user=obj)
        return token.key

推荐阅读