外观
Django框架-构建个人账号信息管理
约 5663 字大约 19 分钟
2026-03-24
本节我们要做一个完整的用户账户系统,包括注册、登录、密码管理、个人资料编辑,还会实现图片上传功能。这些功能会在一个书签管理网站项目中完成。
本节主要内容:
创建登录视图
使用 Django 自带的认证框架
为登录、注销、修改密码、重置密码等功能创建模板
创建用户注册视图
通过自定义 Profile 模型来扩展用户模型
配置项目支持图片上传(媒体文件)
功能概述
- 下面是本章要实现的视图、模板和功能示意图:
- 整体项目目录结构:
bookmarks/ # 外部 bookmarks/ 根目录只是一个项目的容器
├── manage.py # 命令行实用程序,实现与此Django项目进行各种交互
├── bookmarks # 内部 bookmarks/ 目录是当前项目的实际Python包
│ ├── __init__.py # 空文件,代表Python包的标志文件
│ ├── settings.py # 此Django项目的设置/配置 文件
│ ├── urls.py # 该Django项目的URL路由声明
│ ├── asgi.py # ASGI兼容的Web服务器为您的项目提供服务的入口点
│ └── wsgi.py # WSGI兼容的Web服务器为您的项目提供服务的入口点
└── account # account/目录为账户应用程序目录名称(Python包)
├── __init__.py # 空文件,代表Python包的标志文件
├── admin.py # 用于在Django管理站点中注册模型的,使用此站点是可选
├── apps.py # 包括blog应用程序的主要配置
├── migrations # 此目录将包含应用程序的数据库迁移文件(Python包)
│ └── __init__.py
├── static # 静态资源目录(CSS、JS等)
│ └── css
│ └── base.css # 当前应用模板中共用的CSS样式文件
├── templates # 模版目录
│ ├── base.html # 当前应用前端页面父模板
│ ├── account # 当前应用模板目录
│ │ ├── dashboard.html # 控制面板页模板
│ │ ├── edit.html # 编辑账号界面
│ │ ├── login.html # 登录界面
│ │ ├── register_done.html # 账户成功创建提示页
│ │ └── register.html # 创建账户界面(注册)
│ └── registration # 账户注册、登录、重置密码和个人信息的处理模板目录
│ ├── logged_out.html # 退出登录提示页
│ ├── login.html # 执行登录后信息提示页
│ ├── password_change_done.html # 密码已更改提示页
│ ├── password_change_form.html # 更改密码表单页
│ ├── password_reset_complete.html # 密码重置提示页
│ ├── password_reset_confirm.html # 密码重置确认提示页
│ ├── password_reset_done.html # 电子邮件重置密码提示页
│ ├── password_reset_email.html # 请求重置密码的邮箱链接页
│ └── password_reset_form.html # 收取重置密码邮箱表单页
│
├── models.py # 应用程序的数据模型,每个应用程序的必须文件(可留空)
├── tests.py # 在这里为您的应用程序添加测试
└── views.py # 应用程序的逻辑写在这里,HTTP请求、处理并返回响应。- 关于上面完整的静态资源与模板文件的下载: 个人账户信息管理模板文件.zip
一、 构建项目前的准备
注:准备Python3.12版本的虚拟环境,并安装Django5.2版本框架。若已完成请跳过。
1. 使用Python3.12的版本:
Django 5.2 支持 Python 3.10、3.11、3.12 和 3.13,我们这里用 Python 3.12。
如果你的 Python 版本低于 3.12,或者还没有安装 Python,请到 https://www.python.org/downloads/ 下载 Python 3.12 并安装。
python3 --version
python -V
# Python 3.12.92. 创建Python虚拟环境:
- 从 Python 3.3 开始,Python 就自带了
venv模块,可以用来创建轻量级的虚拟环境。
# 1. 创建虚拟环境
python -m venv my_env
# 2. 激活虚拟环境
# Linux下的激活虚拟环境
#source my_env/bin/activate
# Windows下的激活虚拟环境
.\my_env\Scripts\activate
#3. Linux下的验证激活
# (my_env) $ which python
# Windows下的验证激活
(my_env) PS> Get-Command python
# 4. 停用虚拟环境
(my_env) $ deactivate无菌玻璃温室
Terrarium Isolation (Python `venv`)
全球共享系统泥土 (Global/System Env)
🎋
Django 3.2
Django 3.2
my_env (.venv)
全局系统环境就像一片无保护的土地,随便安装依赖极易引起版本污染。使用 python -m venv 就像是建造了一个密闭的无菌玻璃温室。只有在 activate 降下保护罩后,内部种植的依赖(如 Django 5.2)才与外部彻底物理隔离,互不干扰。
The global system is exposed to version conflicts. Using `python -m venv` is like building a glass terrarium. After `activate` drops the isolation dome, dependencies (like Django 5.2) installed inside will never clash with the outside world.
3. 安装Django
- Django 是 Python Web 框架,需要先装好 Python 和 pip。
# 在线安装Django,指定版本安装,目前5.2的最新版为5.2.9
python -m pip install django==5.2
# 默认会安装:Django==5.2.9、sqlparse==0.5.4、asgiref==3.11.0 和 tzdata==2025.3
# 可以使用pip list查看
# 检测当前是否安装Django及版本
python -m django --version
5.2.9
# 我们也可以先下载安装包:pip download django=4.2.18 -d ./二、创建项目与构建z应用
1. 创建项目bookmarks
在虚拟环境中运行以下命令来创建 bookmarks 项目:
$ django-admin startproject bookmarks查看startproject自动创建项目结构如下:
bookmarks/ # 外部bookmarks/根目录只是一个项目的容器
├── manage.py # 命令行实用程序,实现与此Django项目进行各种交互
├── bookmarks # 内部bookmarks/目录是当前项目的实际Python包
│ ├── __init__.py # 空文件,代表Python包的标志文件
│ ├── settings.py # 此Django项目的设置/配置 文件
│ ├── urls.py # 该Django项目的URL路由声明
│ ├── asgi.py # ASGI兼容的Web服务器为您的项目提供服务的入口点
│ └── wsgi.py # WSGI兼容的Web服务器为您的项目提供服务的入口点2. 创建应用程序account
Django 自带一个工具可以自动生成应用程序的基本目录结构,省得你手动建文件夹。
确保你在 manage.py 所在的目录下,然后运行以下命令:
$ cd bookmarks
$ python manage.py startapp account- 这会创建一个 account 目录,结构如下:
bookmarks/
├── manage.py
├─── bookmarks
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── asgi.py
│ └── wsgi.py
└── account # account/目录为账户应用程序目录名称(Python包)
├── __init__.py # 空文件,代表Python包的标志文件
├── admin.py # 用于在Django管理站点中注册模型的,使用此站点是可选
├── apps.py # 包括blog应用程序的主要配置
├── migrations # 此目录将包含应用程序的数据库迁移文件(Python包)
│ └── __init__.py
├── models.py # 应用程序的数据模型,每个应用程序的必须文件(可留空)
├── tests.py # 在这里为您的应用程序添加测试
└── views.py # 应用程序的逻辑写在这里,HTTP请求、处理并返回响应。3. 启用网站Admin管理
(1). 项目配置文件的设置
打开 bookmarks/settings.py 文件,做以下配置:
数据库方面,我们继续使用默认的 SQLite,不需要额外配置 DATABASES:
# SQLite数据库的连接配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}- 设置时区和语言,让admin后台显示中文版界面:
...
LANGUAGE_CODE = 'zh-hans' # 语言设置
TIME_ZONE = 'Asia/Shanghai' # 时区设置
...(2). 数据迁移
- 运行以下命令,把 Admin 管理所需的数据表结构同步到数据库:
$ python manage.py migrate- 也可以用下面的命令查看迁移状态:
$ python manage.py showmigrations- 具体执行效果如下:
# 执行上面命令后的输出结果
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
# 执行下面命令查看迁移状态,具体如下:
$ python manage.py showmigrations
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
[X] 0012_alter_user_first_name_max_length
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial(3). 创建管理员用户
首先,我们需要创建一个能登录管理后台的超级用户。运行以下命令:
$ python manage.py createsuperuser
# 输入用户名,然后按回车:
Username: admin
# 接着输入邮箱地址:
Email address: admin@example.com
# 最后输入密码(至少8位),需要输入两次确认:
Password: **********
Password (again): *********
Superuser created successfully.(4). 启动开发服务器
Admin 管理后台默认就是开启的,我们启动开发服务器来看看效果。
启动命令如下:
$ python manage.py runserver
或
$ python manage.py runserver 0.0.0.0:8000打开浏览器,访问 http://127.0.0.1:8000/admin/
用刚才创建的账号密码登录试试:

三、扩展用户模型
1. 扩展用户模型--增加个人资料
接下来我们在 account 应用中创建一个 Profile 模型,用来存储用户的个人资料。
编辑 account/models.py 文件,代码如下:
from django.conf import settings # 访问Django设置
from django.db import models # 导入Django的模型模块
# 定义用户资料模型
class Profile(models.Model):
# 与Django内置用户模型一对一关联
user = models.OneToOneField(
settings.AUTH_USER_MODEL, # 关联到Django的用户模型
on_delete=models.CASCADE, # 用户被删除时,关联的资料也被删除
verbose_name='用户' # 在Admin中显示的名称
)
# 生日字段,可选
date_of_birth = models.DateField('生日', blank=True, null=True)
# 头像字段,上传到指定目录,可选
photo = models.ImageField(
'头像',
upload_to='users/%Y/%m/%d/',
blank=True
)
# 自定义对应的表名,默认表名:account_profile
class Meta:
db_table="account_profile" # 自定义表名(默认就是这个可省略)
verbose_name = '用户资料' # 在Admin中显示的单数形式名称
verbose_name_plural = '用户资料管理'# 在Admin中显示的复数形式名称
def __str__(self):
return f'{self.user.username} 的个人资料' # 返回用户名作为字串的表示磁吸外骨骼背心
Exosuit Assembly (Extending User with `OneToOneField`)
AUTH_USER_MODEL
username[Built-in]
password[Built-in]
email[Built-in]
1-to-1 Expansion Port
Profile (Custom App)
date_of_birth[Custom]
photo[Custom]
class Profile(models.Model):
user = models.OneToOneField(User, ...)
user = models.OneToOneField(User, ...)
不要直接去修改底层的 User 源码表!最佳实践是建立一个包含自己定制字段的外接背心(如 Profile),通过 OneToOneField 接口咔哒一声磁吸卡死在原始骨架上。组合后,它们在代码中如同一个完整的生命体被调用。
Do not touch the core `User` model code! The best practice is to build an external exosuit (like `Profile`) containing custom fields, and snap it onto the original skeleton using a `OneToOneField`. Once docked, they operate seamlessly as a single entity.
- 这个模型包含了用户的出生日期和头像照片两个字段。
2. 安装 Pillow 并提供媒体文件
要使用
ImageField,需要先安装 Pillow 库。Pillow 是 Python 中最常用的图像处理库,支持多种图像格式。Django 的ImageField底层就依赖它。在终端运行以下命令安装 Pillow:
python -m pip install Pillow==11.0.0- 编辑
settings.py,添加以下配置(后面会给出完整配置):
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'MEDIA_URL是访问用户上传文件的 URL 前缀。MEDIA_ROOT是上传文件在服务器上的实际存储路径。路径和 URL 会动态拼接,确保可移植性。编辑项目主路由文件
bookmarks/urls.py,修改代码如下:
from django.conf import settings # 导入Django的设置模块
from django.conf.urls.static import static # 导入用于处理静态文件的函数
from django.contrib import admin
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
]
# 在调试模式下,添加媒体文件的URL映射
if settings.DEBUG:
# 使用static函数为MEDIA_URL添加URL模式
urlpatterns += static(
settings.MEDIA_URL, # 媒体文件的URL前缀
document_root=settings.MEDIA_ROOT # 媒体文件的存储路径
)拍立得与文件存根分离
Polaroid Splitter (ImageField Local Save vs DB String Path)
📁 BASE_DIR
📂 media
📂 users
📂 2026/03/24
👤
photo.jpg
DB TABLE: account_profile
id | user_id | photo (varchar)
1 | 7 | ________
"users/2026/03/24/photo.jpg"
数据库并不会直接把厚重真实的“图片实体”吞进去!相反,它像老式的拍立得:沉重的物理照片掉落进了本地指定的 MEDIA_ROOT 目录,而只撕下一轻飘飘的“相对存储地址(存根字串)”记入了数据库用来读取。
The database does not ingest heavy physical files! It acts like a Polaroid camera: the heavy physical photograph falls into the local `MEDIA_ROOT` disk directory, while only a lightweight string stub (the relative path) is stored in the database column.
这里我们用
static()辅助函数来让开发服务器能访问媒体文件。注意这段代码只在DEBUG = True时生效。static()函数只适合开发环境使用,不能用于生产环境。Django 处理静态文件的效率很低,生产环境应该用 Nginx 等专业的 Web 服务器来提供静态文件。
3. 编辑项目配置文件
- 在 bookmarks/settings.py 的
INSTALLED_APPS列表中注册 account 应用,注意要放在最前面:
INSTALLED_APPS = [
'account.apps.AccountConfig', # 自定义account应用的配置
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]Django 查找模板时会按照
INSTALLED_APPS中的顺序依次搜索各应用的模板目录。因为django.contrib.admin自带了一套默认的认证模板,而我们需要在account应用中用自己的模板覆盖它们,所以必须把account放在INSTALLED_APPS的最前面,这样 Django 会优先使用我们自定义的模板。继续在 bookmarks/settings.py 配置文件最后添加如下代码:
# 认证相关URL配置
LOGIN_REDIRECT_URL = 'dashboard' # 登录后重定向到控制面板
LOGIN_URL = 'login' # 登录页面URL
LOGOUT_URL = 'logout' # 登出页面URL
# 邮件后台配置,使用控制台后台
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# 生产环境邮件配置示例
# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# EMAIL_HOST = 'smtp.gmail.com'
# EMAIL_PORT = 587
# EMAIL_USE_TLS = True
# EMAIL_HOST_USER = 'your-email@gmail.com'
# EMAIL_HOST_PASSWORD = 'your-app-password'
# DEFAULT_FROM_EMAIL = 'noreply@mysite.com'
# 基础路径配置
# 上面有此代码:BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = 'media/' # 媒体文件URL前缀
MEDIA_ROOT = BASE_DIR / 'media' # 媒体文件存储路径3. 应用数据库迁移
# 创建迁移文件,在account/migrations/目录下:
$ python manage.py makemigrations account
Migrations for 'blog':
account/migrations/0001_initial.py
+ Create model Profile
# 执行应用迁移
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, account, contenttypes, sessions
Running migrations:
Applying account.0001_initial... OK
# 查看迁移状态
python manage.py showmigrations4. 将模型添加到管理站点
现在我们的 account 应用还没出现在 Admin 后台的首页上,需要手动注册一下。
打开 account/admin.py 文件,编辑代码如下:
# 导入Django的admin模块
from django.contrib import admin
# 导入应用中的Profile模型
from .models import Profile
# 注册Profile模型到Django管理后台
@admin.register(Profile)
# 定义Profile模型的管理类
class ProfileAdmin(admin.ModelAdmin):
# 在管理界面中显示的字段
list_display = ['user', 'date_of_birth', 'photo']
# 使用外键选择器来选择关联的用户
raw_id_fields = ['user']
# 可选:自定义 Admin 站点标题
admin.site.site_header = '书签管理系统' # 登录页面和后台顶部标题
admin.site.site_title = '书签管理后台' # 浏览器标签页标题
admin.site.index_title = '欢迎使用书签管理系统' # 首页标题- 编辑 account/apps.py 应用的主配置文件,添加最后一行代码。
from django.apps import AppConfig
# 定义account应用的配置类
class AccountConfig(AppConfig):
# 默认名称(不要改这个)
default_auto_field = 'django.db.models.BigAutoField'
name = 'account' # 应用名称(保持与创建时一致)
verbose_name = '账号管理' # 在Django Admin中显示的应用名称启动服务:
$ python manage.py runserver
或
$ python manage.py runserver 0.0.0.0:8000打开浏览器,访问 http://127.0.0.1:8000/admin/
- 添加用户资料信息

- 成功添加用户资料并上传了一张图片:
大家可以看到在项目的根目录下产生了一个 media 目录,里面存储了刚刚上传成功的图片。
四. 使用 Django 身份验证框架
Django 自带了一套完整的认证框架,能处理用户认证、会话管理、权限控制和用户分组。它还提供了登录、注销、修改密码、重置密码等常用功能的视图。
这个认证框架就是
django.contrib.auth,Django 的很多其他组件也依赖它。当我们用
startproject命令创建新项目时,认证框架已经包含在默认配置里了。它由django.contrib.auth应用和两个中间件组成(配置在settings.py的MIDDLEWARE中):AuthenticationMiddleware:通过 session 把用户和请求关联起来SessionMiddleware:负责处理跨请求的会话数据
中间件可以理解为 Django 在处理请求和响应过程中自动执行的"钩子",会对所有请求统一生效。
认证框架还在
django.contrib.auth.models中定义了以下几个模型:User:用户模型,包含username、password、email、first_name、last_name、is_active等基本字段Group:用户组模型,用来给用户分组Permission:权限模型,用来标记用户或用户组能执行哪些操作
这个框架还提供了默认的认证视图和表单,后面我们会用到。
1. 创建登录视图
我们先用 Django 认证框架来实现用户登录功能。登录视图的处理流程是这样的:
显示登录表单给用户
获取用户提交的用户名和密码
拿用户名和密码去数据库里验证
检查该用户账号是否处于激活状态
验证通过后让用户登录,开启一个认证会话
在 account 应用目录下创建
forms.py文件,写入以下代码:
from django import forms # 导入Django的表单模块
# 登录表单
class LoginForm(forms.Form):
# 声明账号和密码字段
username = forms.CharField(label='账号')
password = forms.CharField(
label='密码',
widget=forms.PasswordInput # 使用密码输入框显示
)- 编辑
account/views.py视图文件,添加以下代码:
# 导入Django内置的认证和登录装饰器
from django.contrib.auth import authenticate, login
from django.http import HttpResponse # 导入HttpResponse类
from django.shortcuts import render # 导入渲染模板的函数
from .forms import LoginForm # 导入登录表单
# 用户登录视图
def user_login(request):
if request.method == 'POST': # 判断请求方式是否为POST
form = LoginForm(request.POST) # 使用POST数据实例化登录表单
if form.is_valid(): # 验证表单数据是否合法
cd = form.cleaned_data # 获取清理后的数据
user = authenticate( # 验证用户身份,返回用户对象
request,
username=cd['username'],
password=cd['password'],
)
if user is not None: # 如果用户存在
if user.is_active: # 检查用户是否激活
login(request, user) # 登录用户
return HttpResponse('登录验证成功!')
else:
return HttpResponse('禁用的账户!')
else:
return HttpResponse('登录无效,请检查您的用户名和密码。')
else:
form = LoginForm() # 如果不是POST请求,创建一个空的登录表单
# 渲染登录模板,传入表单对象
return render(request, 'account/login.html', {'form': form})- 在
account目录下创建urls.py路由文件,代码如下:
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.user_login, name='login'),
]编辑项目 bookmarks 目录下的
urls.py主路由文件,导入include并添加 account 应用的路由。代码如下:
... ...
from django.contrib import admin
from django.urls import include, path # 导入include
urlpatterns = [
path('admin/', admin.site.urls),
path('account/', include('account.urls')), # 配置account应用路由
]
... ...- 在
account应用目录下创建 templates 模板目录和模板文件,结构如下:
templates/
├── account/
│ └── login.html
├── base.html- 编辑
base.html模板,代码如下:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/base.css" %}" rel="stylesheet">
</head>
<body>
<div id="header">
<span class="logo">书签管理</span>
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>其中 account/static/css/base.css 文件: base.css
编辑
account/login.html,代码如下:
{% extends "base.html" %}
{% block title %}登录界面{% endblock %}
{% block content %}
<h1>登录界面</h1>
<p>请使用下面表单进行登录:</p>
<form method="post">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="登录"></p>
</form>
{% endblock %}- 启动开发服务器:
python manage.py runserver- 在浏览器中打开
http://127.0.0.1:8000/account/login/,你会看到登录页面:

- 试试输入一个错误的用户名或密码提交表单,你会看到 "登录无效" 的提示:

- 输入正确的用户名和密码,你会看到 "身份验证成功" 的提示:
到这里,你已经学会了怎么验证用户身份、怎么写自己的登录视图。不过实际开发中,Django 已经帮我们封装好了一套现成的认证视图,接下来我们就来用它。
五、使用 Django 内置的身份验证视图
Django 的认证框架自带了很多现成的表单和视图,可以直接拿来用。前面我们自己写的登录视图是为了帮你理解认证流程,实际项目中更推荐使用 Django 提供的默认认证视图。
Django 提供了以下基于类的视图来处理认证,它们都在
django.contrib.auth.views模块中:LoginView:处理登录表单并完成用户登录LogoutView:注销用户
用于修改密码的视图:
PasswordChangeView:显示修改密码的表单PasswordChangeDoneView:密码修改成功后跳转到的提示页
用于重置密码的视图(忘记密码时使用):
PasswordResetView:让用户提交邮箱,系统会生成一个带 token 的一次性链接发到用户邮箱PasswordResetDoneView:提示用户"重置密码的邮件已发送"PasswordResetConfirmView:用户点击邮件链接后,在这个页面设置新密码PasswordResetCompleteView:密码重置成功后的提示页
开发带有用户系统的 Web 应用时,这些视图能帮你省掉大量重复工作。而且它们都支持自定义,比如指定要用哪个模板、用哪个表单。
想了解更多内置认证视图的细节,可以查看官方文档:https://docs.djangoproject.com/en/5.2/topics/auth/default/#all-authentication-views
全自动开箱盲盒贩售机
Auth Vending Machine (`django.contrib.auth.views` built-ins)
django.contrib.auth.views
Login
Logout
PReset
不需要重新发明轮子去写底层的身份验证!Django 的 auth.views 就像一台装满极品封装功能的自动贩卖机。只需像按按钮一样直接在路由中挂载对应的类视图,几百行复杂的安全验证机制(如密码找回等)就能做到开箱即用。
There is no need to reinvent the wheel for underlying authentication! Django's `auth.views` acts like a vending machine stocked with highly encapsulated features. Simply map the desired Class-Based Views in your URLs, and hundreds of lines of complex security mechanics work out of the box.
1. 导入模板文件:
- 从上面【功能概述】中下载模板文件,在account应用目录下,完成下面模板文件的部署:

2. 完整的视图文件
# account/views.py
# 导入Django内置的认证和登录装饰器
from django.contrib.auth import authenticate, login
# 导入Django内置的登录装饰器
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse # 导入HttpResponse类
from django.shortcuts import render # 导入渲染模板的函数
# 导入自定义的表单类
from .forms import (
LoginForm, # 登录表单
ProfileEditForm, # 用户资料编辑表单
UserEditForm, # 用户信息编辑表单
UserRegistrationForm,# 用户注册表单
)
from .models import Profile # 导入Profile模型
# 用户登录视图
def user_login(request):
if request.method == 'POST': # 判断请求方式是否为POST
form = LoginForm(request.POST) # 使用POST数据实例化登录表单
if form.is_valid(): # 验证表单数据是否合法
cd = form.cleaned_data # 获取清理后的数据
user = authenticate( # 验证用户身份,返回用户对象
request,
username=cd['username'],
password=cd['password'],
)
if user is not None: # 如果用户存在
if user.is_active: # 检查用户是否激活
login(request, user) # 登录用户
return HttpResponse('登录验证成功!')
else:
return HttpResponse('禁用的账户!')
else:
return HttpResponse('登录无效,请检查您的用户名和密码。')
else:
form = LoginForm() # 如果不是POST请求,创建一个空的登录表单
# 渲染登录模板,传入表单对象
return render(request, 'account/login.html', {'form': form})
# 控制面板视图,登录后可见
@login_required #
def dashboard(request):
return render(
request,
'account/dashboard.html', # 模板路径
{'section': 'dashboard'} # 传递给模板的上下文变量
)
# 用户注册视图
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
if user_form.is_valid():
# 创建一个新的用户对象,但暂时不要保存
new_user = user_form.save(commit=False)
# 设置选定的密码
new_user.set_password(user_form.cleaned_data['password'])
# 保存用户对象
new_user.save()
# 创建用户资料对象
Profile.objects.create(user=new_user)
return render(
request,
'account/register_done.html',
{'new_user': new_user},
)
else:
user_form = UserRegistrationForm()
return render(
request,
'account/register.html',
{'user_form': user_form}
)
# 用户资料编辑视图
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(
instance=request.user,
data=request.POST
)
profile_form = ProfileEditForm(
instance=request.user.profile,
data=request.POST,
files=request.FILES,
)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(
request,
'account/edit.html',
{
'user_form': user_form,
'profile_form': profile_form
},
)验证拦截闸机口
Login Turnstile (`@login_required` Decorator Interception)
Guest
@login_required
/account/dashboard/
@login_required 就像是一个带有紫外光扫描的无情安检闸机。无论你试图怎样访问被保护的仪表盘,只要请求上没有盖过“已登录”的合法 Session 印章,就会被无情弹飞重定向到登录页。
`@login_required` acts like a relentless security turnstile with a UV scanner. Try to access the protected dashboard all you want—if your request lacks the authentic 'logged-in' session stamp, you will be violently bounced back and redirected to the login page.
3. 完整的表单模板文件
from django import forms # 导入Django的表单模块
# 导入Django内置的用户模型
from django.contrib.auth import get_user_model
from .models import Profile # 导入Profile模型
# 登录表单
class LoginForm(forms.Form):
# 声明账号和密码字段
username = forms.CharField(label='账号')
password = forms.CharField(
label='密码',
widget=forms.PasswordInput # 使用密码输入框显示
)
# 用户注册表单
class UserRegistrationForm(forms.ModelForm):
# 声明密码和重复密码字段
password = forms.CharField(
label='密码',
widget=forms.PasswordInput
)
password2 = forms.CharField(
label='重复密码',
widget=forms.PasswordInput
)
# 元类,指定表单对应的模型和字段
class Meta:
# 指定使用的用户模型
model = get_user_model()
# 指定使用的字段
fields = ['username', 'first_name', 'email']
# 自定义验证方法,确保两次输入的密码一致
def clean_password2(self):
cd = self.cleaned_data # 获取清理后的数据
# 比较两次输入的密码,是否不同
if cd['password'] != cd['password2']:
# 如果不同,抛出验证错误
raise forms.ValidationError("重复密码不匹配。")
return cd['password2']
# 用户信息编辑表单
class UserEditForm(forms.ModelForm):
# 元类,指定表单对应的模型和字段
class Meta:
model = get_user_model() # 指定使用的用户模型
# 指定使用的字段
fields = ['first_name', 'last_name', 'email']
# 用户资料编辑表单
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['date_of_birth', 'photo']核爆门禁双密匙
Dual-Key Validation (ModelForm `clean_password2`)
P1
STANDBY
P2
用户两次输入的密码,在 clean_password2 方法中如同进行了一次物理光栅扫描。系统对这两把“钥匙”的字符串锯齿进行绝对精确的上下对照,但凡有一个字符不同,就会爆出 ValidationError 阻断注册。
The two passwords entered by the user undergo a process similar to a physical optical scan within the `clean_password2` validation method. The system precisely compares the "teeth" (characters) of both keys; a single mismatch triggers a ValidationError.
4. 完整的路由文件
account应用目录中的urls.py路由文件:
from django.urls import include, path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
# previous login view
# path('login/', views.user_login, name='login'),
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
# change password urls
path(
'password-change/',
auth_views.PasswordChangeView.as_view(),
name='password_change'
),
path(
'password-change/done/',
auth_views.PasswordChangeDoneView.as_view(),
name='password_change_done'
),
# reset password urls
path(
'password-reset/',
auth_views.PasswordResetView.as_view(),
name='password_reset'
),
path(
'password-reset/done/',
auth_views.PasswordResetDoneView.as_view(),
name='password_reset_done'
),
path(
'password-reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm'
),
path(
'password-reset/complete/',
auth_views.PasswordResetCompleteView.as_view(),
name='password_reset_complete'
),
#path('', include('django.contrib.auth.urls')),
path('', views.dashboard, name='dashboard'),
path('register/', views.register, name='register'),
path('edit/', views.edit, name='edit'),
]这些认证 URL 模式的源码可以在这里查看:https://github.com/django/django/blob/stable/5.2.x/django/contrib/auth/urls.py

