用户系统 — 注册、登录、登出
本章你将学会使用 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': '用户名',
}
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 博客'
})
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'),
]
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' # 登出后跳转到首页
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 %}
{% 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 %}
{% 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>
<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;
}
.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 判断登录状态。
现在博客有了完整的用户注册、登录、登出流程。
