使用 Django 令牌身份验证通过基于 class 的视图注销用户的正确方法是什么?

What is the proper way to logout the user via class-based view using Django Token Authentication?

我的登录视图工作正常,我认为注销视图也应该正常工作,但每次我单击按钮注销用户时,都会出现错误 AonymousUser object has not attribute 'auth_token'

我的views.py如下:

class LoginAPIHTML(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'accounts/login.html'

    def get(self, request):        
        serializer = LoginSerializer()
        return Response({'serializer': serializer})

    def post(self, request):
        serializer = LoginSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'serializer': serializer})
        
        user = authenticate(request, username=request.data['email'], password=request.data['password'])
        
        if user:
            Token.objects.get_or_create(user=user)
            login(request, user)
            return redirect('user')

        else:
            return redirect('login')

class LogoutAPIHTML(APIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [TokenAuthentication]

    def get(self, request):
        request.user.auth_token.delete()
        logout(request)
        return redirect('login')

我点击注销按钮的模板如下:

<body>
    <h1>Use Details</h1>
 
    {% if request.user.is_authenticated %}
    <a href="{% url 'logout' %}">
        <input type="button" value="Logout"/>
    </a>
    {% else %}
    <h2>{{ message }}</h2>
    {% endif %}
</body>

我的CustomEmailBackendauthentication.py,定义如下:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class CustomEmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

错误详情如下:

AttributeError at /logout
'AnonymousUser' object has no attribute 'auth_token'
Traceback Switch to copy-and-paste view
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 55, in inner
                response = get_response(request) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py, line 197, in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\decorators\csrf.py, line 54, in wrapped_view
        return view_func(*args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\generic\base.py, line 84, in view
            return self.dispatch(request, *args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 509, in dispatch
            response = self.handle_exception(exc) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 469, in handle_exception
            self.raise_uncaught_exception(exc) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 480, in raise_uncaught_exception
        raise exc …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 506, in dispatch
            response = handler(request, *args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\Downloads\Meistery\Round2\backend_dev_trial_ass_r2\accounts\views.py, line 221, in get
        request.user.auth_token.delete() …
Local vars

我认为(您没有提供 LoginSerializer 的实现)在您的登录视图中您实际上并没有创建身份验证令牌。试试这个:

from rest_framework.authtoken.models import Token


class LoginAPIHTML(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'accounts/login.html'

    def get(self, request):        
        serializer = LoginSerializer()
        return Response({'serializer': serializer})

    def post(self, request):
        serializer = LoginSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'serializer': serializer})
        
        user = authenticate(request, username=request.data['email'], password=request.data['password'])
        
        if user:
            Token.objects.create(user=user)  # Here
            login(request, user)
            return redirect('user')

        else:
            return redirect('login')