Django Auth组件完整版教程:从原理到项目落地

前言: Django 内置的 Auth(用户认证)组件,是后端开发中"用户登录、注册、注销、权限控制"的"万能工具",无需手动搭建用户表、密码加密、Session 管理,开箱即用。

目标: 本文从「核心原理」到「项目完整落地」,结合实际项目场景,手把手教你吃透 Auth 组件,代码可直接复制运行,适合 Django 新手快速上手。

本文适配场景: Django 2.x/3.x/4.x 版本,基于实际项目(front 应用)演示,包含「表单校验+Auth 认证+前端模板+路由配置」全流程,解决新手常见的"密码明文存储""登录后回跳""未登录无法访问页面"等问题。

一、Auth 组件核心原理

1.1 核心作用

Auth 组件本质是 Django 内置的"用户认证系统",封装了 4 大核心功能,无需重复开发:

  • 用户注册:提供加密创建用户的方法,避免密码明文存储

  • 用户登录:校验账号密码、自动写入 Session、维护登录状态

  • 用户注销:清空 Session,重置登录状态

  • 权限控制:通过装饰器,限制"必须登录才能访问"的页面

1.2 核心依赖

使用 Auth 组件无需额外安装,Django 默认自带,只需导入两个核心模块:

复制代码
# 1. 认证核心模块(负责登录、注销、校验)
from django.contrib import auth

# 2. 用户模型(自动生成 auth_user 数据表,存储用户信息)
from django.contrib.auth.models import User

1.3 关键注意点(避坑首选)

  1. 禁止用 User.objects.create() 创建用户(密码明文存储,无法登录);

  2. 必须执行数据库迁移,生成 auth_user 表(否则无法存储用户);

  3. 登录校验分两步:先 authenticate() 校验账号密码,再 login() 写入状态;

  4. 未登录跳转需配置 LOGIN_URL,否则装饰器会报错。

二、Auth 核心用法

2.1 创建用户(3种方法,重点掌握前2种)

Auth 提供 3 种创建用户的方法,核心区别是"密码是否加密"和"是否为超级用户",直接复制代码即可使用:

复制代码
from django.contrib.auth.models import User

# 方法1:创建普通用户(密码密文存储,推荐用于前端注册)
User.objects.create_user(
    username="zhangsan",  # 用户名(必填,唯一)
    password="123456",    # 密码(自动加密)
    email="zhangsan@qq.com"  # 邮箱(可选)
)

# 方法2:创建超级用户(可登录 Django Admin 后台,必填邮箱)
User.objects.create_superuser(
    username="admin",
    password="admin123",
    email="admin@163.com"  # 必须传邮箱,否则报错
)

# 方法3:create() 方法(不推荐,密码明文存储,无法登录)
# User.objects.create(username="test", password="123")  # 错误示范

2.2 用户登录(authenticate + login)

登录流程:获取前端提交的账号密码 → 用 authenticate() 校验 → 校验通过用 login() 写入 Session → 跳转到首页/来源页。

核心说明:

  • authenticate(username, password):校验成功返回用户对象,失败返回 None;

  • auth.login(request, user_obj):无返回值,作用是"写入 Session,将 request.user 赋值为当前用户";

  • next 参数:记录用户未登录时的访问地址,登录后自动回跳(用户体验优化)。

    from django.shortcuts import render, redirect
    from django.contrib import auth

    def login_view(request):
    # GET 请求:返回登录页面
    if request.method == "GET":
    return render(request, "login.html")

    复制代码
      # POST 请求:处理登录逻辑
      username = request.POST.get("username")  # 前端表单name属性值
      password = request.POST.get("pwd")       # 前端表单name属性值
      
      # 1. 校验账号密码
      user_obj = auth.authenticate(username=username, password=password)
      
      # 校验失败:返回登录页,提示错误信息
      if not user_obj:
          return render(request, "login.html", {"msg": "用户名或密码错误"})
      
      # 2. 校验成功:写入登录状态
      auth.login(request, user_obj)
      
      # 3. 登录后回跳(优先回跳之前访问的页面,否则跳首页)
      next_url = request.GET.get("next") or "/index/"
      return redirect(next_url)

2.3 用户注销(logout)

注销逻辑:清空 Session 信息,将 request.user 重置为匿名用户,无需复杂操作,一行代码搞定。

复制代码
from django.shortcuts import redirect
from django.contrib import auth

def logout_view(request):
    # 清空登录状态(无返回值)
    auth.logout(request)
    # 注销后跳回登录页
    return redirect("/login/")

2.4 权限控制(login_required 装饰器)

场景:首页、个人中心、留言板等页面,需要"用户登录后才能访问",未登录自动跳转到登录页。

使用步骤:导入装饰器 → 给需要控制的视图函数添加装饰器 → 配置 LOGIN_URL(未登录跳转地址)。

复制代码
from django.contrib.auth.decorators import login_required
from django.shortcuts import render

# 装饰器:未登录自动跳转到 LOGIN_URL 配置的地址
@login_required
def index(request):
    # 登录后,可通过 request.user 获取当前用户信息
    current_user = request.user
    return render(request, "index.html", {"user": current_user})

配置 LOGIN_URL(项目根目录 settings.py 末尾添加):

复制代码
# Auth 未登录跳转地址(必须配置,否则装饰器报错)
LOGIN_URL = "/login/"

2.5 常用用户判断 & 属性

登录后,可通过 request.user 快速获取当前用户信息,常用操作如下:

复制代码
# 判断用户是否已登录(返回 True/False)
request.user.is_authenticated

# 获取当前用户用户名
request.user.username

# 获取当前用户邮箱
request.user.email

# 获取当前用户ID
request.user.id

# 判断是否为超级用户
request.user.is_superuser

总结

Auth 功能 实现位置 关键代码
创建用户 register_view User.objects.create_user()
用户登录 login_view auth.authenticate() + auth.login()
用户注销 logout_view auth.logout()
权限控制 @login_required @login_required(login_url='login')
用户信息 模板和 shell request.user.xxx

三、项目完整落地(实战核心,直接复制)

本实战基于「front 应用」演示,包含「表单校验+Auth 认证+前端模板+路由配置」全流程,完全贴合实际项目,保留原有业务逻辑(如留言板),新增 Auth 认证功能。

3.1 项目环境准备

  1. 确认项目已创建 front 应用(若未创建,执行命令):

    python manage.py startapp front

  2. 配置 settings.py(启用 Auth 组件+注册 front 应用):

    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth', # Auth 核心组件(默认存在,不要删除)
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'front', # 注册自己的应用
    ]

    新增:未登录跳转地址

    LOGIN_URL = "/login/"

  3. 执行数据库迁移(生成 auth_user 表):

    python manage.py makemigrations
    python manage.py migrate

3.2 完善 forms.py(表单校验,对接 Auth)

包含「注册表单」(手机号校验、密码二次校验)和「留言板表单」(保留原有业务),直接替换 front/forms.py 代码:

复制代码
from django import forms
from django.core import validators
from django.contrib.auth.models import User  # 导入 Auth 用户模型
from .models import Message  # 导入自己的留言板模型(若有)

# 留言板表单(保留原有业务,无需修改)
class MessageBoardForm(forms.ModelForm):
    class Meta:
        model = Message
        fields = ['title', 'content', 'email']
        labels = {
            'title': '留言标题',
            'content': '留言内容',
            'email': '联系邮箱',
        }
        widgets = {
            'content': forms.Textarea(attrs={'rows': 6, 'placeholder': '请输入留言内容'}),
        }
        error_messages = {
            'title': {
                'min_length': '标题最小长度不能少于2个字符!',
                'max_length': '标题最大长度不能超过20个字符!',
            },
            'email': {
                'invalid': '邮箱格式不正确!',
            }
        }

# 注册表单(对接 Auth,新增校验逻辑)
class RegisterForm(forms.Form):
    telephone = forms.CharField(
        label='手机号',
        validators=[validators.RegexValidator(r'^1[3456789]\d{9}$', message='手机号格式不符合要求!')],
        widget=forms.TextInput(attrs={'placeholder': '请输入11位手机号'})
    )
    username = forms.CharField(
        label='用户名',
        min_length=3,
        max_length=20,
        widget=forms.TextInput(attrs={'placeholder': '请输入3-20位用户名'})
    )
    pwd1 = forms.CharField(
        label='密码',
        min_length=6,
        max_length=100,
        widget=forms.PasswordInput(attrs={'placeholder': '请输入6-100位密码'})
    )
    pwd2 = forms.CharField(
        label='确认密码',
        min_length=6,
        max_length=100,
        widget=forms.PasswordInput(attrs={'placeholder': '请再次输入密码'})
    )

    # 局部钩子:校验手机号是否已注册(避免重复注册)
    def clean_telephone(self):
        telephone = self.cleaned_data.get('telephone')
        # 手机号存到 User 表的 username 字段(User 无手机号字段)
        if User.objects.filter(username=telephone).exists():
            raise forms.ValidationError("该手机号已被注册!")
        return telephone

    # 全局钩子:校验两次密码是否一致
    def clean(self):
        cleaned_data = super().clean()
        pwd1 = cleaned_data.get('pwd1')
        pwd2 = cleaned_data.get('pwd2')
        if pwd1 != pwd2:
            self.add_error('pwd2', '两次输入的密码不一致!')
        return cleaned_data

3.3 编写 views.py(视图逻辑,整合 Auth)

包含「首页、注册、登录、注销、留言板」5个核心视图,直接复制到 front/views.py:

复制代码
from django.shortcuts import render, redirect
from django.contrib import auth
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from .forms import RegisterForm, MessageBoardForm
from .models import Message

# 1. 首页(必须登录才能访问)
@login_required
def index(request):
    # 登录后,通过 request.user 获取当前用户信息
    return render(request, 'index.html', {'user': request.user})

# 2. 注册视图(对接 RegisterForm + Auth 创建用户)
def register(request):
    if request.method == 'GET':
        # GET 请求:返回注册页面,渲染表单
        form = RegisterForm()
        return render(request, 'register.html', {'form': form})
    
    # POST 请求:处理注册逻辑,校验表单
    form = RegisterForm(request.POST)
    if form.is_valid():
        # 拿到表单清洗后的数据
        username = form.cleaned_data.get('username')
        telephone = form.cleaned_data.get('telephone')
        password = form.cleaned_data.get('pwd1')
        
        # 核心:用 Auth 方法创建加密用户(禁止用 create())
        User.objects.create_user(
            username=username,  # 用户名
            password=password,  # 加密密码
            email=telephone     # 手机号存到邮箱字段(可选)
        )
        
        # 注册成功,跳转到登录页
        return redirect('/login/')
    
    # 表单校验失败:返回注册页,展示错误信息
    return render(request, 'register.html', {'form': form})

# 3. 登录视图(Auth 标准写法,支持回跳)
def login_view(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    
    # 获取前端提交的账号密码
    username = request.POST.get('username')
    password = request.POST.get('pwd')
    
    # 校验账号密码
    user_obj = auth.authenticate(username=username, password=password)
    if not user_obj:
        return render(request, 'login.html', {'msg': '用户名或密码错误'})
    
    # 写入登录状态
    auth.login(request, user_obj)
    
    # 登录后回跳
    next_url = request.GET.get('next') or '/index/'
    return redirect(next_url)

# 4. 注销视图
def logout_view(request):
    auth.logout(request)  # 清空登录状态
    return redirect('/login/')

# 5. 留言板视图(必须登录才能留言,新增权限控制)
@login_required
def message_board(request):
    if request.method == 'GET':
        form = MessageBoardForm()
        messages = Message.objects.all().order_by('-create_time')
        return render(request, 'message_board.html', {'form': form, 'messages': messages})
    
    form = MessageBoardForm(request.POST)
    if form.is_valid():
        form.save()
        return redirect('/message_board/')
    
    messages = Message.objects.all().order_by('-create_time')
    return render(request, 'message_board.html', {'form': form, 'messages': messages})

3.4 配置 urls.py(路由映射)

配置 front/urls.py,映射所有视图,直接复制:

复制代码
from django.urls import path
from . import views

urlpatterns = [
    # 首页
    path('index/', views.index, name='index'),
    # 注册
    path('register/', views.register, name='register'),
    # 登录
    path('login/', views.login_view, name='login'),
    # 注销
    path('logout/', views.logout_view, name='logout'),
    # 留言板
    path('message_board/', views.message_board, name='message_board'),
]

补充:若项目根目录 urls.py 未包含 front 应用路由,需添加(否则无法访问):

复制代码
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('front.urls')),  # 包含 front 应用路由
]

3.5 编写前端模板(templates 文件夹)

在 front 应用下创建 templates 文件夹,新建 4 个 HTML 文件,直接复制代码,支持表单错误提示、登录状态展示。

1. login.html(登录页面)

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <style>
        .container { width: 400px; margin: 100px auto; }
        .error { color: red; margin-bottom: 10px; }
        input { width: 100%; padding: 8px; margin: 5px 0; }
        button { width: 104%; padding: 10px; background: #007bff; color: white; border: none; border-radius: 4px; }
        a { display: block; text-align: center; margin-top: 10px; color: #007bff; text-decoration: none; }
    </style>
</head>
<body>
    <div class="container">
        <h2 style="text-align: center;">用户登录</h2>
        {% if msg %}
            <div class="error">{{ msg }}</div>
        {% endif %}
        <form action="" method="post">
            {% csrf_token %}  {# Django 防跨站请求伪造,必须加 #}
            <label>用户名:</label>
            <input type="text" name="username" required placeholder="请输入用户名"><br>
            <label>密码:</label>
            <input type="password" name="pwd" required placeholder="请输入密码"><br>
            <button type="submit">登录</button>
            <a href="/register/">还没有账号?去注册</a>
        </form>
    </div>
</body>
</html>

2. register.html(注册页面)

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
    <style>
        .container { width: 400px; margin: 80px auto; }
        .error { color: red; font-size: 12px; }
        input { width: 100%; padding: 8px; margin: 5px 0; }
        button { width: 104%; padding: 10px; background: #28a745; color: white; border: none; border-radius: 4px; }
        a { display: block; text-align: center; margin-top: 10px; color: #007bff; text-decoration: none; }
    </style>
</head>
<body>
    <div class="container">
        <h2 style="text-align: center;">用户注册</h2>
        <form action="" method="post">
            {% csrf_token %}
            {# 自动渲染表单,包含错误提示 #}
            {{ form.as_p }}
            <button type="submit">注册</button>
            <a href="/login/">已有账号?去登录</a>
        </form>
    </div>
</body>
</html>

3. index.html(登录后首页)

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        .container { width: 800px; margin: 50px auto; text-align: center; }
        a { margin: 0 10px; color: #007bff; text-decoration: none; }
        .logout { color: #dc3545; }
    </style>
</head>
<body>
    <div class="container">
        <h1>欢迎 {{ user.username }} 登录系统!</h1>
        <p>当前登录用户:{{ user.username }} | 邮箱:{{ user.email }}</p>
        <div>
            <a href="/message_board/">去留言板</a>
            <a href="/logout/" class="logout">退出登录</a>
        </div>
    </div>
</body>
</html>

4. message_board.html(留言板页面)

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>留言板</title>
    <style>
        .container { width: 800px; margin: 50px auto; }
        .form-box { margin-bottom: 30px; padding: 20px; border: 1px solid #eee; border-radius: 4px; }
        .message { margin: 10px 0; padding: 10px; border-bottom: 1px solid #eee; }
        .title { font-weight: bold; }
        .content { margin: 5px 0; }
        .email { font-size: 12px; color: #666; }
        a { color: #007bff; text-decoration: none; }
    </style>
</head>
<body>
    <div class="container">
        <h2>留言板</h2>
        <a href="/index/">返回首页</a>
        
        <div class="form-box">
            <h3>发表留言</h3>
            <form action="" method="post">
                {% csrf_token %}
                {{ form.as_p }}
                <button type="submit">提交留言</button>
            </form>
        </div>
        
        <div class="message-list">
            <h3>留言列表</h3>
            {% for msg in messages %}
                <div class="message">
                    <div class="title">{{ msg.title }}</div>
                    <div class="content">{{ msg.content }}</div>
                    <div class="email">联系邮箱:{{ msg.email }}</div>
                </div>
            {% empty %}
                <div>暂无留言,快来发表第一条留言吧!</div>
            {% endfor %}
        </div>
    </div>
</body>
</html>

3.6 启动项目测试(完整流程)

执行启动命令,按照以下顺序测试,确保所有功能正常:

复制代码
python manage.py runserver
  1. 访问注册页:http://127.0.0.1:8000/register/,测试表单校验(手机号格式、密码长度、两次密码一致);

  2. 注册成功后,自动跳转到登录页,输入账号密码登录;

  3. 登录后跳转到首页,可看到当前用户信息,点击"去留言板"发表留言;

  4. 未登录状态下,直接访问 http://127.0.0.1:8000/index/,会自动跳转到登录页;

  5. 点击"退出登录",回到登录页,再次访问首页会被拦截。

现在可以直接访问:

功能 新 URL
📝 注册 http://127.0.0.1:8000/register/
🔐 登录 http://127.0.0.1:8000/login/
💬 首页 http://127.0.0.1:8000/
📄 发布文章 http://127.0.0.1:8000/article/

🧪 完整测试流程

  1. 打开浏览器访问 http://127.0.0.1:8000/register/
  2. 填写注册信息
    • 用户名:test123
    • 邮箱:test@example.com
    • 密码:password123
    • 确认密码:password123
  3. 点击"注册"按钮 → 重定向到登录页
  4. 输入刚才的账户登录 → 成功显示首页,看到用户名和注销按钮
  5. 尝试访问 /article/ → 可以正常发布文章
  6. 点击"注销"按钮 → 清空会话,重定向到登录页
  7. 再次访问 /article/ → 被重定向到登录页 ✅

在 SSMS 中查询这三个数据

1. 查询用户表 auth_user(test123)

复制代码
USE django_form_demo;
SELECT id, username, email, date_joined
FROM auth_user;

2. 查询留言板表 front_message(刚才发的帖子)

复制代码
USE django_form_demo;
SELECT id, title, content, email, create_time
FROM front_message;

3.在 SSMS 查询文章表 front_article

复制代码
USE django_form_demo;
SELECT id, title, content, category, create_time
FROM front_article;

或者查看所有字段:

复制代码
USE django_form_demo;
SELECT *
FROM front_article
ORDER BY create_time DESC;

四、常见问题&解决方案

常见问题 解决方案
创建用户后,登录提示"用户名或密码错误" 1. 检查是否用了 create() 方法(改用 create_user());2. 确认密码输入正确;3. 执行数据库迁移
@login_required 装饰器报错 settings.py 中添加 LOGIN_URL = "/login/",确保路由正确
注册时手机号无法重复校验 检查 clean_telephone 钩子函数,确保过滤的是 User 表的 username 字段(手机号存于此)
登录后无法回跳之前的页面 确保登录视图中添加了 next_url = request.GET.get("next") or "/index/",并 redirect(next_url)
前端表单提交报 403 Forbidden 表单中忘记添加 {% csrf_token %} 标签,添加即可解决

五、总结

Django Auth 组件的核心优势是"封装完善、开箱即用",无需手动处理密码加密、Session 管理等繁琐操作,重点掌握以下 5 点,就能应对绝大多数项目的用户认证需求:

  1. 创建用户:用 create_user()(普通用户)、create_superuser()(超级用户);

  2. 登录流程:authenticate() 校验 → login() 写入状态;

  3. 注销流程:logout() 清空状态;

  4. 权限控制:@login_required 装饰器 + LOGIN_URL 配置;

  5. 用户信息:登录后通过 request.user 获取。

本文所有代码均可直接复制运行,适配 Django 2.x/3.x/4.x 版本,若需扩展功能(如自定义用户模型、密码重置),可在评论区留言,后续补充。

相关推荐
lifewange1 小时前
Hadoop 完整入门详解
大数据·hadoop·分布式
斯维赤1 小时前
Python学习超简单第八弹:网络编程
网络·python·学习
Irene19912 小时前
Oracle 21c XE 大数据开发常用 SQL 语法总结(不同 Oracle 版本,sql 语法大部分通用)
大数据·sql·oracle
ZKNOW甄知科技2 小时前
燕千云ITR深度解析:大型企业如何建立服务价值流?
运维·人工智能·后端·科技·安全·自动化·用户运营
ZGi.ai2 小时前
自然语言查数据库:Text-to-SQL工程实现与企业落地细节
数据库·sql·nl2sql·text-to-sql
huizhixue-IT2 小时前
华为职业认证新版全景图及重认证规则变更预通知-5月7日开始生效!Datacom和 Security支持跨技术方向的重认证!
运维·服务器
小樱花的樱花2 小时前
Linux文件系统的类型和结构
linux·运维·服务器
JSON_L3 小时前
Fastadmin中实现敏感词管理
数据库·php·fastadmin
我喜欢山,也喜欢海3 小时前
Java和go在并发上的表现为什么不一样
java·python·golang