修改URL后request.user.is_authenticated失效问题求助
我是Django初学者,基于教程开发设备管理系统,原有登录、登出、设备增删改查功能。为了让仅登录用户能访问home视图,我修改了login_register.html的表单action为"home/",但修改后navbar.html中用{% if request.user.is_authenticated %}判断用户认证状态、切换Login/Logout按钮的功能失效,始终显示Login按钮。
相关代码
原views.py
from django.shortcuts import render, redirect from django.http import HttpResponse from .models import Information from django.db.models import Q from django.contrib import messages from django.contrib.auth import authenticate, login, logout from .forms import MyForm def home(request): q = request.GET.get('q') if request.GET.get('q') !=None else '' information_search = Information.objects.filter( Q(host__icontains=q) | Q(hostname__icontains=q) | Q(port__icontains=q) | Q(platform__icontains=q) | Q(username__icontains=q) | Q(password__icontains=q) | Q(groups__icontains=q) ) sort_info = [] informations = Information.objects.all() for i in informations: if i.groups not in sort_info: device_group = i.groups sort_info.append(device_group) information_count=information_search.count() context = {'informations':informations, 'information_search':information_search, 'information_count':information_count, 'sort_info':sort_info} return render(request, 'polls/home.html', context) def view_data(request, pk): information = Information.objects.get(id=pk) context = {'information':information} return render(request, 'polls/view_data.html', context) def loginPage(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') try: user = User.objects.get(username=username) except: messages.error(request, 'User does not exist') user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return redirect('home') else: messages.error(request, "Username or password does not exist") context = {} return render(request, 'polls/login_register.html', context) def logoutUser(request): logout(request) return redirect('home') def edit_data(request, pk): information = Information.objects.get(id=pk) form = MyForm(instance=information) if request.method == 'POST': form = MyForm(request.POST, instance=information) if form.is_valid(): form.save() return redirect('home') context = {'form': form} return render(request, 'polls/room_form.html', context) def delete_data(request, pk): information = Information.objects.get(id=pk) if request.method == 'POST': information.delete() return redirect('home') return render(request, 'polls/delete.html', {'obj': information}) def my_form(request): if request.method == "POST": form = MyForm(request.POST) if form.is_valid(): form.save() return redirect('home') else: form = MyForm() return render(request, 'polls/room_form.html', {'form': form})
修改后的login_register.html
{% extends 'main.html' %} {% block content %} <div> <form method="POST" action="home/"> {% csrf_token %} <label>Username:</label> <input type="text" name="username" placeholder="Enter Username" /> <label>Password:</label> <input type="password" name="password" placeholder="Enter Password"> <input type="submit" value="login"> </form> </div> {% endblock content %}
navbar.html
<a href="/polls"> <h1>LOGO</h1> </a> <form method="GET" action="{% url 'home' %}"> <input type="text" name="q" placeholder="Search Devices..."> </form> {% if request.user.is_authenticated %} <a href="{% url 'logout' %}">Logout</a> {% else %} <a href="{% url 'login' %}">Login</a> {% endif %} <hr>
问题原因
你修改表单action为"home/"后,登录请求直接提交到了home视图,完全跳过了loginPage视图的认证逻辑——只有loginPage视图会调用login(request, user)完成用户会话的认证绑定。直接提交到home视图时,用户名密码没有被验证,也没有创建登录会话,所以request.user始终是匿名用户,导航栏自然一直显示Login按钮。
另外,你想实现“仅登录用户可访问home视图”的需求,也不应该通过修改表单action来实现,正确做法是给视图添加登录验证装饰器。
解决方案
1. 恢复登录表单的提交目标
修改login_register.html的表单action,要么留空(默认提交到当前的loginPage视图),要么用Django的{% url %}标签指向登录路由:
{% extends 'main.html' %} {% block content %} <div> <!-- 用{% url 'login' %}确保提交到登录视图,前提是urls.py中给loginPage视图命名为login --> <form method="POST" action="{% url 'login' %}"> {% csrf_token %} <label>Username:</label> <input type="text" name="username" placeholder="Enter Username" /> <label>Password:</label> <input type="password" name="password" placeholder="Enter Password"> <input type="submit" value="login"> </form> </div> {% endblock content %}
2. 给home视图添加登录验证
在views.py中导入login_required装饰器,给home视图加上,实现仅登录用户可访问:
from django.contrib.auth.decorators import login_required # 新增导入 from django.contrib.auth.models import User # 补充原视图缺失的User模型导入 # 给home视图添加装饰器,未登录用户会被重定向到登录页 @login_required(login_url='login') def home(request): # 原视图代码不变
3. 修复loginPage视图的缺失依赖
原loginPage视图中没有导入User模型,会导致运行报错,必须补充上述的from django.contrib.auth.models import User导入。
额外说明
- 导航栏的
{% if request.user.is_authenticated %}逻辑本身没有问题,只要用户通过login(request, user)完成登录,会话中的用户信息会被正确设置,导航栏会自动切换为Logout按钮。 - 其他需要登录才能访问的视图(比如
edit_data、delete_data),都可以添加@login_required装饰器来保护。
内容的提问来源于stack exchange,提问作者Super MaxLv4

