首页 > 解决方案 > Django登录方法给出递归错误

问题描述

我尝试制作一个自定义身份验证视图,将用户保存在会话中,login(request, user)但它给了我

调用 Python 对象时超出最大递归深度

我尝试使用from django.contrib.auth import login as django_login不混淆方法导入登录方法,但它仍然不起作用。

没有登录方法,身份验证工作得很好,但它不会将用户保存在会话中,所以没有用。

这是完整的views.py文件:

from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
from rest_framework.response import Response
from rest.models import User
from .serializers import UserSerializer
from django.contrib.auth import get_user_model
from django.contrib.auth import authenticate as django_authenticate
from django.contrib.auth import login as django_login
from django.contrib.auth.hashers import check_password
import json

class UserCreateAPIView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)

class Authentication(authentication.BaseAuthentication):

    def authenticate(self, request):
        email = request.POST.get('email', None)
        password = request.POST.get('password', None)
        if not email or not password:
            raise exceptions.AuthenticationFailed(_('No credentials provided.'))

        credentials = {
            get_user_model().USERNAME_FIELD: email,
            'password': password
        }

        user = django_authenticate(**credentials)

        if user is None:
            raise exceptions.AuthenticationFailed(_('Invalid username/password.'))

        if not user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

        django_login(request, user)
        return (user, None)  # authentication successful

class LoginView(APIView):
    authentication_classes = (SessionAuthentication, Authentication)
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):
        content = {
            'user': str(request.user),
            'auth': str(request.auth),
        }
        return Response(content)

def CheckLoginView(requst):
    current_user = requst.user
    return current_user

这是回溯:

            response = get_response(request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = self.process_exception_by_middleware(e, request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/views/decorators/csrf.py in wrapped_view
        return view_func(*args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/views/generic/base.py in view
            return self.dispatch(request, *args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in dispatch
            response = self.handle_exception(exc) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in handle_exception
            self.raise_uncaught_exception(exc) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in raise_uncaught_exception
        raise exc …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in dispatch
            self.initial(request, *args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in initial
        self.perform_authentication(request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in perform_authentication
        request.user …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py in login
    if hasattr(request, 'user'): …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py in login
    if hasattr(request, 'user'): …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars

最后 4 种方法只是一遍又一遍地重复。

标签: djangoauthenticationdjango-rest-framework

解决方案


django.contrib.auth.authenticate将调用后端以尝试对用户进行身份验证。通过在您的身份验证后端调用它,它将永远循环,因为django.contrib.auth.authenticate将调用您的后端,该后端将调用该函数等等。

因此,您需要从您尝试覆盖和调用的身份验证方法中,super().authenticate(request)而不是django.contrib.auth.authenticate.


推荐阅读