Django @login_required实现登陆认证

发布于:2025-08-12 ⋅ 阅读:(16) ⋅ 点赞:(0)

@login_required 是 Django 提供的一个装饰器 (decorator),用于保护视图函数,确保只有已登录的用户才能访问该视图。它是 Django 认证系统的核心组件之一,提供了简单而强大的访问控制功能。

环境准备

安装 Django

pip install django

项目创建步骤

1. 创建 Django 项目

django-admin startproject myproject
cd myproject

2. 创建应用

python manage.py startapp bookapp
项目结构

        

3. 配置项目 (settings.py)

myproject/settings.py中添加以下配置:

INSTALLED_APPS = [
    # ...其他应用
    'bookapp',
]

# 登录URL配置
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/books/'
LOGOUT_REDIRECT_URL = '/login/'

为什么要在 settings.py 中配置登录相关 URL?

Django 的认证系统设计了三个核心 URL 配置,用于处理认证流程中的页面跳转:

  1. LOGIN_URL (/login/)

    • 作用:指定未登录用户访问受保护页面时的重定向目标
    • 原理:当用户尝试访问被@login_required保护的视图时,Django 会检查用户认证状态,如果未登录,会自动重定向到该 URL
  2. LOGIN_REDIRECT_URL (/books/)

    • 作用:指定用户登录成功后的默认跳转页面
    • 应用场景:当用户直接访问登录页面并成功登录后,会跳转到该 URL
  3. LOGOUT_REDIRECT_URL (/login/)

    • 作用:指定用户登出后的跳转页面
    • 安全考虑:登出后重定向到登录页面是常见的安全实践

这些配置是全局设置,为整个项目提供一致的认证体验,避免在每个视图中重复定义相同的跳转逻辑。

4. 创建视图 (bookapp/views.py)

from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import LoginView
from django.shortcuts import render

class CustomLoginView(LoginView):
    template_name = 'login.html'

@login_required
def book_list(request):
    # 示例书籍数据
    books = [
        {'id': 1, 'title': 'Django for Beginners', 'author': 'William S. Vincent'},
        {'id': 2, 'title': 'Python Crash Course', 'author': 'Eric Matthes'},
        {'id': 3, 'title': 'Two Scoops of Django', 'author': 'Daniel Roy Greenfeld'},
    ]
    return render(request, 'book_list.html', {'books': books})

5. 配置 URL

myproject/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('bookapp.urls')),
]

bookapp/urls.py
from django.urls import path
from django.contrib.auth.views import LogoutView
from . import views

urlpatterns = [
    path('login/', views.CustomLoginView.as_view(), name='login'),
    path('logout/', LogoutView.as_view(), name='logout'),
    path('books/', views.book_list, name='book_list'),
]

6. 创建模板文件

创建模板目录
mkdir -p bookapp/templates
login.html
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
    <style>
        .login-container { max-width: 400px; margin: 50px auto; padding: 20px; box-shadow: 0 0 10px #ccc; }
        .form-group { margin-bottom: 15px; }
        label { display: block; margin-bottom: 5px; }
        input { width: 100%; padding: 8px; box-sizing: border-box; }
        button { background-color: #4CAF50; color: white; padding: 10px 15px; border: none; cursor: pointer; }
        button:hover { background-color: #45a049; }
        .error { color: red; margin-bottom: 15px; }
    </style>
</head>
<body>
    <div class="login-container">
        <h2>Login</h2>
        {% if form.errors %}
            <div class="error">Your username and password didn't match. Please try again.</div>
        {% endif %}
        
        <form method="post">
            {% csrf_token %}
            <div class="form-group">
                <label for="id_username">Username</label>
                {{ form.username }}
            </div>
            <div class="form-group">
                <label for="id_password">Password</label>
                {{ form.password }}
            </div>
            <button type="submit">Login</button>
        </form>
    </div>
</body>
</html>
book_list.html
<!DOCTYPE html>
<html>
<head>
    <title>Book List</title>
    <style>
        .container { max-width: 800px; margin: 0 auto; padding: 20px; }
        .logout-link { text-align: right; margin-bottom: 20px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <div class="container">


    <!-- 在book_list.html中替换原有的登出链接 -->
<div class="logout-link">
    <form action="{% url 'logout' %}" method="post">
        {% csrf_token %}
        <button type="submit" style="background: none; border: none; color: blue; text-decoration: underline; cursor: pointer;">
            Logout
        </button>
    </form>
</div>


        <h1>Book List</h1>
        <table>
            <tr>
                <th>ID</th>
                <th>Title</th>
                <th>Author</th>
            </tr>
            {% for book in books %}
            <tr>
                <td>{{ book.id }}</td>
                <td>{{ book.title }}</td>
                <td>{{ book.author }}</td>
            </tr>
            {% endfor %}
        </table>
    </div>
</body>
</html>

7.执行数据库迁移

ps:如果不执行数据库迁移,没有用户表,创建超级用户会失败

python manage.py migrate

8. 创建超级用户 (管理员)

python manage.py createsuperuser

9. 运行开发服务器

python manage.py runserver

实现效果:

http://127.0.0.1:8000/books

未登陆时,直接访问books,会跳转至登陆页

登陆成功后才能查看页面