Django开发指南中文版:从入门到实战的完整Web开发手册

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Django是一款基于Python的高效开源Web框架,广泛用于快速构建安全且可维护的网站。本《Django开发指南中文版》是一份面向初学者与进阶开发者的全面参考资料,系统讲解了从环境搭建、项目结构、模型设计、视图与URL配置、模板系统、表单处理到用户认证、中间件、性能优化及生产部署等核心内容。通过清晰的实践指导和深入的技术解析,帮助开发者掌握Django全栈开发流程,提升项目构建能力,适用于各类Web应用开发场景。

Django开发环境搭建与核心概念入门

哎呀,是不是刚打开编辑器就一脸懵?别慌!咱们今天不整那些“首先…其次…”的八股文,直接上干货。想象一下:你正坐在咖啡馆里,手边是杯快凉的美式,脑子里盘算着怎么把那个拖了三个月的个人博客项目启动起来——而Django,就是你的救星 🚀

环境隔离的艺术:从“我机器上能跑”到团队协作无压力

先问一句:有没有经历过“在我电脑上明明好好的,怎么部署上去就炸了”这种灵魂拷问?😅 想必不少人都被这个坑绊过。其实问题的根源很简单—— 依赖冲突

Python项目就像一锅炖菜,不同项目需要不同的“香料组合”。有的要Django 3.x配旧版数据库驱动,有的又要用Django 5的新特性。如果所有包都装在系统全局环境里,那简直就是一场灾难。

所以啊,第一课不是写代码,而是学会“划地盘”——虚拟环境搞起来!

venv 打造专属沙箱

好消息是:从Python 3.3开始,你根本不需要额外安装什么 virtualenv ,因为官方自带了一个更轻量、更稳定的工具—— venv 。它就像是给每个项目发了个独立的小房间,谁也别想打扰谁。

来,动手试试:

python -m venv myblog_env

就这么一行命令,你就拥有了一个干净整洁的开发沙箱。目录结构长这样:

myblog_env/
├── bin/           # Linux/macOS下的可执行文件(pip、python等)
├── Scripts/       # Windows专用脚本区
├── lib/           # 所有第三方库都会安家在这里
└── pyvenv.cfg     # 配置文件,记录基础Python路径

💡 小贴士:建议把虚拟环境名起得有意义一点,比如 myblog_env shop_api_venv ,避免日后面对一堆叫 env1 env2 的神秘文件夹抓耳挠腮。

如果你想要更精细的控制,还可以加上这些参数:

python -m venv --clear --copies myblog_env
  • --clear :如果同名目录存在,先清空再重建(适合重置环境)
  • --copies :强制复制Python解释器而不是软链接(某些Windows或Docker环境下更稳定)

流程图走一波,帮你理清整个创建逻辑:

graph TD
    A[开始] --> B{检查Python版本}
    B -->|Python >= 3.3| C[执行: python -m venv env_name]
    B -->|Python < 3.3| D[需先安装virtualenv]
    C --> E[生成独立目录结构]
    E --> F[包含bin/, lib/, pyvenv.cfg]
    F --> G[环境创建完成]

看到没?整个过程简单得不像话。但记住一件事:一定要把你这个 myblog_env/ 加进 .gitignore

# .gitignore
__pycache__/
*.pyc
.env
myblog_env/
.DS_Store

不然哪天手滑提交了,同事拉下代码一看——好家伙,几百兆的虚拟环境全塞进来了 😵‍💫


跨平台激活指南:别让操作系统卡住你的节奏

接下来就是“开门入住”的环节了——激活虚拟环境。这里有个小痛点:不同系统的激活命令不一样,新人最容易在这一步出错。

平台 激活命令 退出命令
Linux/macOS source myblog_env/bin/activate deactivate
Windows CMD myblog_env\Scripts\activate.bat deactivate
PowerShell myblog_env\Scripts\Activate.ps1 deactivate

注意看PowerShell那一行, .ps1 结尾的脚本默认是被禁用的!第一次运行会提示权限错误。解决办法也很简单:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

这句的意思是:“允许当前用户运行本地编写的脚本”,既安全又实用。

激活成功后,你会看到终端前面多了一串括号:

(myblog_env) $ python --version
Python 3.11.4
(myblog_env) $ which pip
/Users/you/project/myblog_env/bin/pip

(myblog_env) 这个小标记太重要了,它时刻提醒你:“你现在在一个封闭空间里工作,请放心大胆地装包。”

为了防止队友误操作,我还喜欢加个自动化检测脚本:

import sys

def is_venv():
    return hasattr(sys, 'real_prefix') or \
           (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)

if __name__ == "__main__":
    if is_venv():
        print("✅ 当前运行在虚拟环境中")
    else:
        print("❌ 未检测到虚拟环境,请先激活")

这段代码可以嵌入CI/CD流程中作为前置检查,避免“忘记激活环境导致打包失败”的低级错误。


依赖管理终极方案: requirements.txt 分层设计

现在环境准备好了,该装Django了:

pip install "Django>=4.2,<5.0"

为啥不用固定版本?因为 >=4.2,<5.0 既能锁定大版本,又能自动获取小版本的安全更新,平衡了稳定性与安全性。

装完之后,立刻导出依赖清单:

pip freeze > requirements.txt

生成的内容大概是这样的:

Django==4.2.7
sqlparse==0.4.4
asgiref==3.7.2

每一行都是精确版本号,确保任何人还原环境时都能得到完全一致的结果。

但这只是初级玩法。真正专业的做法是 分层管理依赖

requirements/
├── base.txt      # 基础依赖(Django、常用工具)
├── dev.txt       # 开发专用(debug-toolbar、flake8)
└── prod.txt      # 生产环境(gunicorn、whitenoise)

然后在 dev.txt 里这样写:

-r base.txt
django-debug-toolbar==4.2.0
flake8==6.1.0
pytest-django==4.5.2

而在 prod.txt 里:

-r base.txt
gunicorn==21.2.0
whitenoise==6.6.0
psycopg2-binary==2.9.7

这样做有几个巨大好处:
- 团队开发只装必要的调试工具,不影响生产;
- 部署时可以精准控制运行时依赖;
- CI测试可以选择性加载,节省时间;

恢复环境也变得超级清晰:

# 新成员入职第一步
git clone https://github.com/team/myblog.git
cd myblog

# 第二步:建环境
python -m venv venv
source venv/bin/activate  # 或对应平台命令

# 第三步:装依赖
pip install -r requirements/dev.txt

整个流程丝滑如德芙,再也不用担心“为什么我的页面样式不对?”“你是不是忘了装xxx?”这类扯皮问题。

顺便提一嘴,国内网络环境下推荐加镜像源提速:

pip install -r requirements/dev.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

清华源yyds!👏

下面是完整的依赖流转流程图:

graph LR
    A[开发者本地开发] --> B[pip freeze > requirements.txt]
    C[新成员加入项目] --> D[git clone 项目代码]
    D --> E[创建并激活虚拟环境]
    E --> F[pip install -r requirements.txt]
    F --> G[环境一致性达成]

这套机制看似简单,实则解决了团队协作中最头疼的问题之一。信我,坚持这么做,你会成为办公室最受欢迎的人 😎


Django项目的初始化流程:别急着写业务逻辑!

OK,环境搭好了,接下来是不是就想冲进去写视图、建模型?停!先深呼吸,听我说一句掏心窝子的话: 一个项目的命运,往往在初始化那一刻就决定了

很多人图省事,随手敲一行 django-admin startproject mysite ,结果后面越写越乱,文件到处飞,最后不得不重构……何必呢?

我们一步一步来,稳扎稳打。

初始化命令背后的秘密

进入虚拟环境后,先确认Django装好了:

django-admin --version
# 输出:4.2.7

没问题就开始创建项目骨架:

django-admin startproject mysite .

注意末尾那个 . !它的作用是把项目文件直接放在当前目录,而不是再嵌套一层 mysite/mysite/ 。虽然看起来只是少一层目录,但在后续导入路径处理上能省去无数麻烦。

生成的结构如下:

mysite/
├── manage.py
├── mysite/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
└── requirements/          # 我们手动创建的

这里面最关键的几个角色是谁?

  • manage.py :万能指挥官,所有命令都要靠它发起;
  • settings.py :项目的“大脑”,一切配置从这儿出;
  • urls.py :路由中枢,决定请求去哪儿;
  • wsgi.py :生产部署的入口点;
  • asgi.py :支持WebSocket和异步任务的通道;

你可以把 manage.py 理解成遥控器,按一下 runserver 就启动服务器,按一下 migrate 就同步数据库,非常方便。

它的内部实现其实也不复杂:

#!/usr/bin/env python
import os
import sys

if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError("无法导入Django,请检查是否已安装") from exc
    execute_from_command_line(sys.argv)

重点看第6行: os.environ.setdefault(...) 设置了默认配置模块路径。这意味着你在任何地方调用 python manage.py xxx ,Django都知道该去哪里找 settings.py

这也是为什么你不应该随便移动这些核心文件的原因——一旦路径断了,整个项目就瘫痪了。


settings.py :掌控全局的关键配置

现在打开 mysite/settings.py ,你会发现一大堆变量。别怕,我们挑重点说几个,这几个直接关系到你的项目能不能活下去。

DEBUG模式:开发与生产的分水岭
DEBUG = True  # 开发时设为True,方便看错误详情

但!只要上线,必须改成 False 。否则一旦出错,用户就能看到完整的堆栈信息,包括你的数据库密码、密钥路径……想想都吓人。

所以最佳实践是:

import os
DEBUG = os.environ.get('DJANGO_DEBUG', '') == 'True'

然后通过环境变量控制:

export DJANGO_DEBUG=True && python manage.py runserver

这样就不需要改代码也能切换模式,适合自动化部署。

SECRET_KEY:不能泄露的生命线
SECRET_KEY = 'your-secret-key-here'

这个值用于加密session、生成token等关键操作。如果被人拿到,相当于把家门钥匙交给了黑客。

所以千万不要硬编码!正确的做法是从环境变量读取:

from decouple import config  # 需要先pip install python-decouple

SECRET_KEY = config('SECRET_KEY')

配合一个 .env 文件:

SECRET_KEY=abcdef1234567890yourverylongsecretkeyhere
DEBUG=True
DB_NAME=myblog

然后把这个 .env 加进 .gitignore ,永远不提交到仓库。

🔐 提示:推荐使用 dj-config-builder django-environ 这类库,它们专为配置管理而生,支持多种格式和层级合并。

数据库配置:SQLite够用吗?

默认配置是SQLite:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

对于小型项目或者初期原型来说完全OK,但它有个致命弱点: 不支持并发写入 。一旦流量上来,多个用户同时提交表单就会卡死。

所以正式项目强烈建议用PostgreSQL:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DB_NAME'),
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASS'),
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

PostgreSQL不仅性能更强,还支持JSON字段、全文搜索、地理数据等高级功能,长远来看值得投入。

ALLOWED_HOSTS:防止HTTP Host头攻击

DEBUG=False 时,必须设置:

ALLOWED_HOSTS = [
    'example.com',
    'www.example.com',
    'localhost',
    '127.0.0.1',
]

这是为了防御一种叫做“Host头伪造”的攻击。比如黑客发送一个 Host: evil.com 的请求,试图让你的应用返回敏感内容。有了这个白名单,Django就会直接拒绝非法域名的访问。

总结一下生产环境的关键配置模板:

import os
from decouple import config

DEBUG = False
SECRET_KEY = config('SECRET_KEY')
ALLOWED_HOSTS = ['example.com', 'api.example.com']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DB_NAME'),
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASS'),
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

STATIC_ROOT = '/var/www/myblog/static/'
MEDIA_ROOT = '/var/www/myblog/media/'

把这些配置外置、加密、动态加载,才是现代Web应用的标准姿势 ✅


数据模型构建:如何设计一张经得起时间考验的表?

终于到了最激动人心的部分——建模!很多人以为ORM就是“把类变成表”,其实远远不止。一个好的模型设计,不仅要反映业务逻辑,还要考虑未来扩展性、查询效率、数据一致性等问题。

让我们以一个博客系统为例,看看怎么一步步打造出健壮的数据结构。

模型类设计三要素:字段、约束、关系

先定义作者和文章两个基本模型:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)

    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='articles')

    class Meta:
        db_table = 'blog_articles'
        ordering = ['-pub_date']

来,逐个拆解亮点:

  • CharField(max_length=100) :字符串字段,必须指定最大长度,对应数据库的 VARCHAR
  • EmailField(unique=True) :自带邮箱格式验证 + 唯一索引,防重复注册神器;
  • TextField() :不限长度的大文本,适合文章正文;
  • DateTimeField(auto_now_add=True) :创建时自动记录时间,再也不用手动赋值;
  • BooleanField(default=False) :状态开关,默认未发布;
  • ForeignKey(..., on_delete=models.CASCADE) :外键关联,删除作者时连带删掉所有文章;
  • related_name='articles' :反向查询快捷方式, author.articles.all() 就能拿到作者所有文章;

⚠️ 注意:不要滥用 CASCADE !如果是评论系统,删用户不该连评论一起删,否则历史数据全没了。这时候可以用 SET_NULL PROTECT

再来看个复杂点的例子——订单系统:

class Order(models.Model):
    STATUS_CHOICES = [
        ('pending', '待处理'),
        ('shipped', '已发货'),
        ('delivered', '已送达'),
        ('cancelled', '已取消'),
    ]

    order_number = models.CharField(max_length=50, unique=True, db_index=True)
    total_amount = models.DecimalField(max_digits=10, decimal_places=2)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    customer_note = models.TextField(blank=True, null=True)

这里有几点值得细品:

  • choices 参数:不仅限制取值范围,还能在Admin后台自动生成下拉菜单,用户体验满分;
  • DecimalField :金融计算必须用它!浮点数会有精度丢失问题, 0.1 + 0.2 != 0.3 懂的都懂;
  • db_index=True :为订单号加索引,让 Order.objects.get(order_number='...') 飞起来;
  • blank=True, null=True :说明这个字段在表单里可以为空,数据库也允许NULL;

特别是 auto_now auto_now_add 的区别:

  • auto_now_add :只在新建时设置一次;
  • auto_now :每次保存都会更新,适合“最后修改时间”;

千万别搞混了,不然你可能会遇到“每次访问详情页订单时间都被刷新”的诡异bug 😂


模型继承:别复制粘贴了,用抽象基类!

有没有发现很多模型都有 created_at updated_at 这两个字段?每次都要写一遍?太累了!

Django提供了三种继承方式,其中最实用的是 抽象基类

class TimestampedModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True  # 关键!不会生成实际数据表

class Product(TimestampedModel):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=8, decimal_places=2)

这样一来, Product 表就会自动包含三个字段: id , created_at , updated_at , name , price 。而且以后新增的模型都可以轻松复用。

另外两种继承模式也值得了解:

类型 是否生成新表 典型用途
抽象基类 字段复用(时间戳、软删除标志)
多表继承 扩展已有模型(如User→Admin)
代理模型 修改行为而不改结构(排序、方法重写)

举个例子,你想让用户分为普通用户和VIP用户,但共用同一张表:

class User(models.Model):
    name = models.CharField(max_length=50)
    points = models.IntegerField(default=0)

class VIPUser(User):
    class Meta:
        proxy = True

    def is_vip(self):
        return self.points > 1000

VIPUser User 共享数据表,但你可以定义专属方法,非常适合做权限判断或定制逻辑。

下面是三种继承模式的类图对比:

classDiagram
    class AbstractBase {
        +created_at: DateTimeField
        +updated_at: DateTimeField
        <<abstract>>
    }
    class Product {
        +name: CharField
        +price: DecimalField
    }
    class Place {
        +name: CharField
        +address: CharField
    }
    class Restaurant {
        +serves_pizza: BooleanField
        +rating: FloatField
    }
    AbstractBase <|-- Product : Inherits
    Place <|-- Restaurant : Multi-table Inheritance

记住一句话: 能用组合不用继承,能用抽象不用多表 。过度设计只会增加维护成本。


Meta元类:不只是名字,更是行为定义

Meta 类藏了很多宝藏配置,很多人只知道改表名,其实它还能干大事!

比如联合唯一约束:

class Enrollment(models.Model):
    student = models.ForeignKey('Student', on_delete=models.CASCADE)
    course = models.ForeignKey('Course', on_delete=models.CASCADE)
    enrollment_date = models.DateField(auto_now_add=True)

    class Meta:
        unique_together = ('student', 'course')  # 同一个学生不能重复报名

不过官方现在更推荐用 constraints

from django.db.models import UniqueConstraint

class Meta:
    constraints = [
        UniqueConstraint(
            fields=['student', 'course'],
            name='unique_student_course_enrollment'
        ),
        models.CheckConstraint(
            check=models.Q(enrollment_date__lte=models.Now()),
            name='enrollment_date_cannot_be_future'
        )
    ]

看到了吗?不仅能定义唯一性,还能加 检查约束 ,比如报名日期不能是未来的!

还有权限管理:

class Report(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()

    class Meta:
        verbose_name = "报告"
        verbose_name_plural = "报告"
        permissions = [
            ("can_view_sensitive", "可以查看敏感报告"),
            ("can_export_report", "可以导出报告数据"),
        ]

这样一来,在视图中就可以这样控制访问:

from django.contrib.auth.decorators import permission_required

@permission_required('myapp.can_view_sensitive')
def view_sensitive_report(request):
    ...

甚至可以在模板里判断:

{% if user.has_perm('myapp.can_export_report') %}
    <button>导出数据</button>
{% endif %}

这才是真正的“权限下沉”到模型层,而不是散落在各个视图里。


URL路由与视图:打造灵活高效的请求处理器

Django的URL系统可以说是全框架最优雅的设计之一。它既支持简洁的路径匹配,又能处理复杂的正则规则,还能实现反向解析,简直是路由界的六边形战士 🛡️

模块化路由设计:告别臃肿的urls.py

很多人一开始就把所有URL塞进主 urls.py ,结果几千行代码挤在一起,根本没法维护。

正确姿势是用 include() 拆分:

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

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

然后每个应用自己管自己的路由:

# blog/urls.py
from django.urls import path
from . import views

app_name = 'blog'  # 命名空间,防止冲突
urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('post/<int:post_id>/', views.post_detail, name='post_detail'),
]

这样做的好处太多了:
- 各团队可以独立开发,互不影响;
- 路由结构清晰,一眼看出模块划分;
- 支持命名空间,模板里用 {% url 'blog:post_list' %} 就不会撞名;

下面是请求分发的全过程:

graph TD
    A[用户请求 /blog/post/123/] --> B{根路由匹配}
    B --> C[/blog/ 匹配成功]
    C --> D[调用 include('blog.urls')]
    D --> E{子路由匹配}
    E --> F[path('post/<int:post_id>/', ...)]
    F --> G[执行 views.post_detail 视图]
    G --> H[返回HTTP响应]

整个过程像快递分拣一样高效,层层递进,职责分明。


动态参数捕获:让URL更有意义

静态路由只能做展示页,真正强大的是动态路由。

Django支持两种方式:

1. 简单转换器(推荐)
path('article/<int:id>/', views.article_detail),
path('user/<str:username>/', views.profile_view),

内置转换器包括:

转换器 匹配规则 示例
str 非空字符串(不含 / john
int 正整数 123
slug 字母数字连字符 hello-world
uuid UUID字符串 a1b2c3d4-...
path 可含斜杠的任意字符串 docs/tutorial/install/
2. 正则表达式(复杂场景)
re_path(r'^product/(?P<category>[\w-]+)/(?P<id>[0-9]+)/$', views.product_detail)

命名捕获组 (?P<name>...) 会被自动传给视图函数:

def product_detail(request, category, id):
    return HttpResponse(f"Category: {category}, ID: {id}")

SEO友好又语义清晰,完美!


反向解析:彻底告别硬编码URL

还在写 <a href="/blog/post/123/"> ?太危险了!万一哪天改了URL结构,全站链接全废。

Django提供反向解析机制:

from django.urls import reverse

url = reverse('blog:post_detail', kwargs={'post_id': 123})
# 结果:/blog/post/123/

在模板里更方便:

<a href="{% url 'blog:post_list' %}">所有文章</a>
<a href="{% url 'blog:post_detail' post_id=post.id %}">{{ post.title }}</a>

甚至可以在模型里定义绝对路径:

class Post(models.Model):
    title = models.CharField(max_length=200)

    def get_absolute_url(self):
        return reverse('blog:post_detail', args=[self.pk])

然后模板里直接调:

<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>

无论URL怎么变,链接永远正确。这才是专业开发的态度 👍


安全认证体系:保护用户数据的最后一道防线

最后压轴登场的是Django内置的 auth 系统。说实话,这是我见过最完整、最易用的身份认证模块,没有之一。

登录登出:只需几行代码

from django.contrib.auth import login, logout
from django.contrib.auth.forms import AuthenticationForm
from django.shortcuts import render, redirect

def user_login(request):
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request, user)
            return redirect('home')
    else:
        form = AuthenticationForm()
    return render(request, 'login.html', {'form': form})

def user_logout(request):
    logout(request)
    return redirect('login')

就这么简单!Django自动处理session写入、CSRF防护、密码哈希等所有细节。


密码安全机制揭秘

Django默认使用PBKDF2算法+盐值哈希,即使两个用户密码相同,存储的哈希值也完全不同。

手动操作也很方便:

from django.contrib.auth.hashers import make_password, check_password

hashed = make_password('mypassword')
is_valid = check_password('mypassword', hashed)  # True

而且支持多种哈希算法栈,可平滑升级:

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',  # 最安全
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',  # 默认
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]

密码重置全流程

Django连“忘记密码”都想好了:

# urls.py
path('password-reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),

流程全自动:
1. 用户输入邮箱 → 发送带token的链接
2. 点击链接 → 验证token有效性(有效期3天)
3. 设置新密码 → 更新并清除token

graph TD
    A[用户点击“忘记密码”] --> B{输入注册邮箱}
    B --> C[系统查找用户]
    C -- 找到 --> D[生成唯一Token和URL]
    D --> E[通过Email发送重置链接]
    E --> F[用户点击链接]
    F --> G[验证Token有效性]
    G -- 有效 --> H[允许设置新密码]
    G -- 过期或无效 --> I[提示错误]
    H --> J[更新密码并清除Token]
    J --> K[跳转至登录页]

配合邮件后端配置(Gmail/SMTP),几分钟就能上线。


写在最后:Django的魅力在于“约定优于配置”

你看,我们从环境搭建一路讲到认证系统,几乎没有哪里需要“发明轮子”。Django的强大之处就在于: 它已经替你想好了90%的问题,并给出了优雅的解决方案

与其花时间造重复的轮子,不如深入理解这套成熟架构的设计哲学。当你真正掌握MTV模式、ORM机制、URL分发、中间件链等工作原理后,你会发现——

开发,原来可以这么轻松 🎉

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Django是一款基于Python的高效开源Web框架,广泛用于快速构建安全且可维护的网站。本《Django开发指南中文版》是一份面向初学者与进阶开发者的全面参考资料,系统讲解了从环境搭建、项目结构、模型设计、视图与URL配置、模板系统、表单处理到用户认证、中间件、性能优化及生产部署等核心内容。通过清晰的实践指导和深入的技术解析,帮助开发者掌握Django全栈开发流程,提升项目构建能力,适用于各类Web应用开发场景。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值