You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改URL后request.user.is_authenticated失效问题求助

Django登录后导航栏认证状态判断失效问题

我是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 %}  
<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:35:21