现在位置: 首页 > Django 教程 > 正文

用户系统 — 注册、登录、登出

本章你将学会使用 Django 内置的认证系统,实现用户注册、登录和登出功能。


Django 内置 auth 系统

Django 自带一套完整的用户认证模块:

  • 内置 User 模型(用户名、密码、邮箱等)
  • 内置登录/登出视图(无需自己写逻辑)
  • 内置的权限和组管理
  • 表单验证和安全防护(CSRF、XSS)

这个模块是 django.contrib.auth,在创建项目时已经默认注册到了 INSTALLED_APPS。


注册页面

Django 内置了登录/登出视图,但没有内置注册视图,需要我们自己写。

第一步:创建注册表单

实例

# 文件路径:blog/forms.py(新建文件)
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

class RegisterForm(UserCreationForm):
    """自定义注册表单:继承 UserCreationForm,添加邮箱字段"""
    email = forms.EmailField(
        label='邮箱',
        required=True,
        help_text='请输入有效的邮箱地址。'
    )

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
        labels = {
            'username': '用户名',
        }

第二步:编写注册视图

实例

# 文件路径:blog/views.py 新增
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib import messages
from .forms import RegisterForm

def register(request):
    """用户注册视图"""
    # 如果用户已登录,直接跳转首页
    if request.user.is_authenticated:
        return redirect('index')

    if request.method == 'POST':
        # 用户提交了注册表单
        form = RegisterForm(request.POST)
        if form.is_valid():
            user = form.save()              # 保存用户到数据库
            login(request, user)            # 注册后自动登录
            messages.success(request, f'注册成功,欢迎你,{user.username}!')
            return redirect('index')
    else:
        # GET 请求:显示空白注册表单
        form = RegisterForm()

    return render(request, 'blog/register.html', {
        'form': form,
        'title': '注册 - RUNOOB 博客'
    })

Django 的 messages 框架用于在请求之间传递一次性消息(如「注册成功」)。在模板中渲染 messages 区域,用户就能看到操作反馈。它和 session 配合使用,消息显示一次后自动消失。


登录与登出

Django 内置了登录和登出视图,只需在路由中引入即可。

实例

# 文件路径:blog/urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('post/<int:pk>/', views.post_detail, name='post_detail'),
    path('register/', views.register, name='register'),

    # Django 内置登录视图
    # template_name:指定使用哪个模板
    path('login/', auth_views.LoginView.as_view(
        template_name='blog/login.html',
        redirect_authenticated_user=True  # 已登录用户访问 login 直接跳转
    ), name='login'),

    # Django 内置登出视图
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]

在 settings.py 中配置登录登出的跳转地址:

实例

# 文件路径:blog_project/settings.py 末尾添加
LOGIN_URL = 'login'                    # 未登录用户访问保护页面时跳转到登录页
LOGIN_REDIRECT_URL = 'index'           # 登录成功后跳转到首页
LOGOUT_REDIRECT_URL = 'index'          # 登出后跳转到首页

创建认证相关模板

登录模板

实例

<!-- 文件路径:blog/templates/blog/login.html -->
{% extends 'blog/base.html' %}

{% block title %}登录 - RUNOOB 博客{% endblock %}

{% block content %}
<div class="auth-form">
    <h2>登录</h2>
    <form method="post">
        {% csrf_token %}
        <div class="form-group">
            <label>用户名</label>
            {{ form.username }}
        </div>
        <div class="form-group">
            <label>密码</label>
            {{ form.password }}
        </div>
        {% if form.errors %}
            <p class="error-msg">用户名或密码错误,请重试。</p>
        {% endif %}
        <button type="submit" class="btn-submit">登录</button>
    </form>
    <p class="form-footer">
        还没有账号?<a href="{% url 'register' %}">立即注册</a>
    </p>
</div>
{% endblock %}

注册模板

实例

<!-- 文件路径:blog/templates/blog/register.html -->
{% extends 'blog/base.html' %}

{% block title %}注册 - RUNOOB 博客{% endblock %}

{% block content %}
<div class="auth-form">
    <h2>注册</h2>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn-submit">注册</button>
    </form>
    <p class="form-footer">
        已有账号?<a href="{% url 'login' %}">立即登录</a>
    </p>
</div>
{% endblock %}

{% csrf_token %} 是 Django 的安全机制,防止跨站请求伪造攻击。任何 POST 表单必须包含它,否则 Django 会拒绝请求(403 错误)。这个标签会生成一个隐藏的 input,包含随机的 CSRF token。


在导航栏显示登录状态

更新 base.html 的导航栏,根据登录状态显示不同内容。

实例

<!-- 修改 blog/templates/blog/base.html 的导航栏部分 -->
<header class="navbar">
    <a href="/" class="logo">RUNOOB 博客</a>
    <nav>
        <a href="/">首页</a>

        {% if user.is_authenticated %}
            {# 已登录:显示用户名和登出按钮(user 是 Django 自动注入的) #}
            <span class="user-name">{{ user.username }}</span>
            <a href="{% url 'logout' %}">登出</a>
        {% else %}
            {# 未登录:显示登录和注册链接 #}
            <a href="{% url 'login' %}">登录</a>
            <a href="{% url 'register' %}">注册</a>
        {% endif %}
    </nav>
</header>

Django 的模板上下文处理器会自动将 {{ user }} 注入到每个模板中,无需在 views.py 中手动传递。你可以通过 user.is_authenticated 判断用户是否登录。


登录页面样式

实例

/* 在 base.html 的 style 中追加 */
.auth-form {
    max-width: 400px;
    margin: 40px auto;
    padding: 30px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.08);
}

.auth-form h2 {
    margin-bottom: 24px;
    text-align: center;
}

.auth-form .form-group {
    margin-bottom: 16px;
}

.auth-form label {
    display: block;
    margin-bottom: 6px;
    font-weight: 500;
}

.auth-form input {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid #ddd;
    border-radius: 6px;
    font-size: 14px;
}

.btn-submit {
    width: 100%;
    padding: 12px;
    background: #2c3e50;
    color: #fff;
    border: none;
    border-radius: 6px;
    font-size: 16px;
    cursor: pointer;
    margin-top: 10px;
}

.error-msg {
    color: #e74c3c;
    font-size: 14px;
}

.form-footer {
    margin-top: 16px;
    text-align: center;
    font-size: 14px;
}

.user-name {
    color: #2c3e50;
    font-weight: 500;
}

本章小结

本章你接入了 Django 内置认证系统:继承了 UserCreationForm 创建注册表单、使用 LoginView/LogoutView 实现登录登出、用 csrf_token 保护 POST 请求、在模板中使用 user.is_authenticated 判断登录状态。

现在博客有了完整的用户注册、登录、登出流程。