Django 4.2中已登录用户request.user.is_authenticated返回false问题
问题背景与代码
我是Django 4.2新手,搭建网站时遇到登录登出异常问题,相关代码如下:
登录视图函数
def loginUsers(request): context = {} if request.method == 'POST': email = request.POST['email'] upass = request.POST['password'] user = authenticate(request, email=email, password=upass) if user is not None: login(request, user) messages.success(request, 'Login successful') time.sleep(2) return redirect(reverse('index')) else: messages.error(request, 'Invalid user') return redirect(reverse('login')) return render(request, 'auth_pages/login.html', context)
首页与登出视图函数(位于index应用的views.py)
def loadIndexPage(request): context = {} print(request.user.is_authenticated) return render(request, 'pages/index.html', context) def logoutUser(request): if request.method == 'POST': logout(request) messages.success(request, 'You are logged out') return redirect(reverse('login'))
模板中的身份判断代码
{% if request.user.is_authenticated %} <p>Hey there user</p> {% else %} <p>Not working</p> {% endif %}
问题表现
- 登出功能无法正常生效,浏览器地址栏出现csrftokenmiddleware相关内容
- 打印
request.user.is_authenticated始终返回False - 模板中的身份判断始终显示“Not working”
- 为
loadIndexPage添加@login_required装饰器后,被重定向到未创建的页面 - 数据库中看到
is_authenticated列值为false
疑问
- 我的代码是否存在问题?
- 是否需要手动将
is_authenticated列设为True?
解答
关于疑问2:不需要手动设置is_authenticated
首先明确:is_authenticated不是数据库字段,它是Django用户对象的只读动态属性,用户登录后Django会自动维护这个状态,完全不需要手动修改数据库相关值。你在数据库里看到的应该是is_active字段(控制用户是否可用),和is_authenticated无关。
代码与配置中的问题排查与修复
删除登录视图中的冗余代码
删掉time.sleep(2),这行代码会阻塞服务器请求,毫无必要,还可能导致登录状态未及时写入响应就跳转,引发异常。完善登出视图的请求处理
当前logoutUser视图只处理POST请求,如果用户通过GET请求访问该视图(比如直接输入URL),会返回错误。补充默认返回逻辑,同时确保登出按钮通过POST表单提交且携带CSRF令牌:def logoutUser(request): if request.method == 'POST': logout(request) messages.success(request, 'You are logged out') return redirect(reverse('login')) # 处理非POST请求,重定向回首页 return redirect(reverse('index'))模板中的登出表单需正确设置CSRF:
<form method="POST" action="{% url 'logout' %}"> {% csrf_token %} <button type="submit">登出</button> </form>地址栏出现csrftoken相关内容,大概率是因为表单未携带CSRF令牌,被Django的CSRF中间件拦截后抛出异常提示。
检查模板上下文处理器配置
确保settings.py的TEMPLATES配置中,context_processors包含django.contrib.auth.context_processors.auth,这样request.user才能在模板中正常访问:TEMPLATES = [ { # ...其他配置 'OPTIONS': { 'context_processors': [ # ... 'django.contrib.auth.context_processors.auth', # ... ], }, }, ]解决@login_required的重定向问题
默认情况下,@login_required会重定向到/accounts/login/,你需要在settings.py中设置LOGIN_URL为你的登录页面的URL名称或路径:LOGIN_URL = 'login' # 这里的'login'是你登录视图的URL名称处理基于Email的认证逻辑
Django默认的认证后端通过username字段验证身份,如果你用email字段登录,需二选一:- 确保用户模型中
username字段的值和email一致; - 自定义认证后端支持通过email查找用户,示例如下(放在应用的
backends.py中):
然后在from django.contrib.auth.backends import ModelBackend from django.contrib.auth import get_user_model class EmailBackend(ModelBackend): def authenticate(self, request, email=None, password=None, **kwargs): UserModel = get_user_model() try: user = UserModel.objects.get(email=email) except UserModel.DoesNotExist: return None if user.check_password(password): return usersettings.py中配置:AUTHENTICATION_BACKENDS = [ 'your_app.backends.EmailBackend', 'django.contrib.auth.backends.ModelBackend', ]
- 确保用户模型中
确认核心中间件配置
检查settings.py的MIDDLEWARE配置,确保包含以下中间件(顺序不能错):MIDDLEWARE = [ # ... 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', # ... ]这两个中间件是维护用户会话和认证状态的核心,缺失或顺序错误会导致登录状态无法正常传递。
内容的提问来源于stack exchange,提问作者theocode

