引言
在当今 Web 应用快速迭代的时代,选择一个高效、稳定且可扩展的后端框架至关重要。Django ,作为 Python 生态中最成熟、最具影响力的 Web 框架之一,自诞生以来就以"The Web framework for perfectionists with deadlines (为追求完美又有截止期限的人准备的框架)"著称。随着 Django 5 的发布,它在性能、安全性以及现代 Web 开发体验上再次迈出了重要一步。
Django 是什么?
Django 是一个基于 Python 的 全栈 Web 框架 ,采用 MTV(Model-Template-View) 架构模式,内置了大量开箱即用的功能,包括:
-
ORM(对象关系映射),无需手写 SQL 即可操作数据库
-
强大的后台管理系统(Admin)
-
完善的 URL 路由与中间件机制
-
表单系统、模板引擎、用户认证与权限管理
-
默认启用多项安全机制(CSRF、XSS、SQL 注入防护等)
这些特性使得开发者可以专注于业务逻辑本身,而不是重复造轮子。
Django 5 的核心特性(简述)
Django 5 延续了一贯的稳健风格,在保持向后兼容性的同时,引入了更现代化的特性,例如:
-
更完善的 异步支持(ASGI)
-
对 Python 新版本的全面支持
-
性能与安全性的持续优化
-
更清晰的 API 设计和长期维护保障(LTS 生态)
这使 Django 在企业级应用、内容管理系统(CMS)、后台管理系统以及复杂业务场景中依然具备强大竞争力
Django 与其他主流框架的对比
| 框架 | 定位 | 优势 | 适用场景 |
|---|---|---|---|
| Django | 全栈框架 | 功能完整、安全、开发效率高 | 企业级应用、后台系统 |
| Flask | 微框架 | 轻量、灵活、自由度高 | 小型项目、API 服务 |
| FastAPI | 现代 API 框架 | 高性能、自动文档、异步友好 | 高并发 API、微服务 |
| Spring Boot | Java 生态 | 生态成熟、强类型、稳定性高 | 大型 Java 企业项目 |
| Laravel | PHP 框架 | 语法优雅、生态丰富 | PHP Web 应用 |
本文的学习目标 使用Django的ORM实现对数据库的CRUD
什么是 ORM?为什么新手一定要学?
在传统开发中,我们往往需要直接编写 SQL 语句来操作数据库,例如:
-
INSERT插入数据 -
SELECT查询数据 -
UPDATE修改数据 -
DELETE删除数据
而 Django 提供的 ORM(Object Relational Mapping,对象关系映射),允许我们:
用 Python 类和对象,来操作数据库中的表和数据
简单来说:
-
数据库表 ⇨ Python 类(Model)
-
表中的一行数据 ⇨ 类的一个对象
-
SQL ⇨ Python 方法
这对新手来说有几个巨大优势:
-
不需要一开始就精通 SQL
-
代码更直观、更安全
-
避免 SQL 注入等常见问题
-
同一套代码可适配多种数据库(SQLite / MySQL / PostgreSQL)
本系列你将学到什么?
在接下来的内容中,我们将以 Django 5 为基础,从零开始:
-
创建 Django 项目与应用
-
认识 Django 的项目结构
-
定义 Model,理解数据库表
-
使用 ORM 完成 增 / 删 / 改 / 查(CRUD)
-
通过视图(View)与 URL 将数据展示出来
即使你没有后端经验、只会一点 Python,也可以跟着一步步完成。
将理论有点干巴 下面我们进入实战教程
环境的准备:
首先 你得具备一定的python环境 才可以进入Django的学习
新建一个文件夹(命名最好不带中文) 专门用于 Django 然后用pycharm打开

在下面点开终端 输入指令
pip install django # 默认下载最新的版本
这个下载太慢了 可以配置 镜像源
暂时使用 pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple
# 就之后默认的下载源改为清华源 加快下载的速度
永久使用pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
这里Django下载完成后 会在python解释器的文件夹中 多出两个文件
在python/lib/site-packages目录下 会多出一个django文件 这是源码

在python/scripts/下 会出现一个 Django-admi.exe 这是工具 类似pip scrapy 用于构建django项目

在终端中输入 创建新建项目的指令
django-admin startproject 项目名称
完了之后会在项目结构中生成 如下图的结构

第二个方法 通过 pycharm建项目 (必须是pycharm专业版)
点击上面任务栏中的file/new project /选择Django

这样建出来的项目 对比命令行的区别就是会多出一个文件夹(templates 放一些静态文件的) 而且setting里面会多一行代码 指的就是这个文件的路径
刚学 我们可以把这两个东西删了 推荐使用命令行的方式去创建项目

创建的文件目录解释:
manage.py 项目的管理 项目的启动 创建app 数据管理
settings.py项目配置
urls.py Url 和函数的对应关系
然后创建app
python manage.py startapp 名字
创建完之后别忘了在这个settings文件中注册app


接下来写一个页面和对应的请求
在urls里面定义路由 也就是浏览器访问的地址 一个地址对应着一个视图函数

在视图函数里面写返回至前端的信息

写完之后 我们在终端输入
python manage.py runserver #运行django项目
输入地址 可以看到返回的字符串

也可以返回一个页面 页面的存放也有规定
一般的静态页面在当前项目下新建一个templates文件夹 如果用pycharm建的项目就不需要新建

然后需要修改一下配置
在settings中 目录这里加上这行即可 表示存放的文件夹在项目目录下


在视图函数中返回静态页面

最后在终端启动项目 python manage.py runserver 浏览器中输入url即可访问成功

以上就是返回页面
在一个典型的 Web 应用中,整体流程可以简化为:
浏览器 → URL → 视图(View) → 数据库 → 视图 → 返回响应
Django 的作用就是把这些步骤规范化并自动化:
-
URL 负责分发请求
-
View 负责业务逻辑
-
Model 负责数据结构与数据库交互
-
Template 负责页面展示
其中,Model + ORM 是连接 Python 代码与数据库的桥梁。
Django 操作数据库(ORM)
连接数据库
修改settings里面的配置(数据库名 用户 密码 端口等等) 默认为sqlite 这里我使用的是mysql
按如下代码格式修改即可 数据库引擎 名字 主机 密码 用户名 端口等

此时 需要我们在数据库中自己创建 数据库 比如我的是django
我这里采用的是图形化界面 Navicat

这样配置了还不行 还需要以下的配置
我这里使用的是pymysql 作为驱动 其它的驱动也可以 有的会下载不成功 比较麻烦 建议使用pymysql 需安装这个模块 之后在你创建app名字里面的init_py文件中 将此模块设置为驱动
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
接着我们在model里面写数据库相关的操作

OK 写完之后运行如下的两行代码

看到如上的信息说明就执行成功了

增
我们先有表结构 才能向数据库中添加数据 所以我们先在Model.py中定义一个类
python
from django.db import models
# Create your models here.
class Article(models.Model):
# 这个CharField就相当于 数据库中的varchar 这个语法不一样 还有很多的Field参数需要知道
# 之后再说
title = models.CharField(max_length=100)
content = models.TextField()
created_id = models.DateTimeField(auto_now_add=True) # 这个就是以后插入数据时的时间添加进去 默认的 不需要传参
原理解析
-
Article类 ⇨ 数据库中的一张表 -
每个字段 ⇨ 表中的一列
-
models.Model⇨ ORM 的核心父类 -
auto_now_add=True⇨ 插入数据时自动填充时间
之后我们需要运行数据库迁移的两行代码 把这个变更同步到数据库中
📌 迁移的本质:
-
makemigrations根据 Model 的变化生成迁移文件(Python 代码) -
migrate把迁移文件转换为 SQL 并执行
Model 是"设计图",数据库是"成品"


以上的情况就是成功了 数据库中的表名默认是app的名字_类名 这个也是可以改的 之后再说

在映射url与views之后 向表中插入数据

python
from django.shortcuts import render, HttpResponse
# 导入类
from .models import Article
# Create your views here.
def add(request):
Article.objects.create(
title='第一篇文章',
content='The world is your oyster!'
)
return HttpResponse('插入成功')
项目跑起来后 输入对应的url即可 以下就是成功向数据库中插入了一行数据

查
同样地
python
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.hello),
path('add/', views.add),
path('read/', views.read)
]
def read(request):
# 查找所有的数据
result = Article.objects.all()
print(result.values())
return HttpResponse('查询成功')


还有其它的查询语法 比如
python
# 全部
Post.objects.all()
# 单条
Post.objects.get(pk=1)
# 条件过滤
Post.objects.filter(title__contains='测试')
# 排序
Post.objects.order_by('-created_at')
# 只取部分字段
Post.objects.values('id', 'title')
📌 原理说明:
-
filter()⇨ 返回 QuerySet(懒执行) -
get()⇨ 立即执行,且只返回一条
大家可以试试
改

python
def update(request):
# 先查到要修改的数据 然后再修改 最后保存
article = Article.objects.get(id=1)
article.title = '修改后的标题'
article.save()
return HttpResponse('修改标题成功')


删



到此基本的曾删改查就已经完成了
现在对这个流程有个基本的了解之后
讲一下这个配置url 以上的url代码是写在在根项目下的 但是开发中和哪个app相关的请求路由 就写在哪个app下面的urls.py(需要自己创建)中 然后在根项目中引入即可 相当于是父子包含关系

在主路由中引入 也就是
python
from django.urls import path, include
urlpatterns = [
path('demo1/', include('demo1.urls'))
]

对以上的内容熟悉了之后 我们将继续实现 使用Template展示数据库数据
返回web页面
| 组件 | 负责什么 |
|---|---|
| View | 获取数据、处理逻辑 |
| Template | 展示数据 |
| Model | 数据存储 |
View 负责"给数据",Template 负责"怎么显示" 以下是实现过程
请求 → View
↓
ORM 查询数据
↓
render(request, 模板, 数据)
↓
Template 渲染 HTML
↓
返回给浏览器
OK 来一个url和view的映射 还有html页面

python
def show(request):
article = Article.objects.all()
return render(request, 'demo1/show.html', {'article': article})
-
"demo1/show.html"模板路径
-
{'article': article}字典,传递给模板的数据
-
Django 自动完成:
-
查找模板
-
渲染模板
-
返回 HttpResponse
-
接着我们写html模板 学过前端的就非常顺手
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文章列表</title>
</head>
<body>
<h1>文章列表</h1>
<ul>
{% for article in articles %}
<li>
<strong>{{ article.title }}</strong>
{{ article.content }}
</li>
{% endfor %}
</ul>
</body>
</html>
{{ article.title }} 用来输出变量 Django 会自动做 HTML 转义(防 XSS)
{% for article in articles %} 模板中的控制结构 不是 Python,但语法非常接近
项目运行起来 访问即可

接着我们来写web页面的CRUD 写出好看的页面
python
from django.core.validators import MinValueValidator, MaxValueValidator
# 在models.py中定义表结构
class Student(models.Model):
GENDER_CHOICES = [
('M', '男'),
('F', '女'),
('O', '其它'),
]
# 添加中文标签
name = models.CharField('姓名', max_length=100)
student_id = models.CharField('学号', max_length=20, unique=True)
# 年龄额外需要做个范围限制 # 需要导入数值校验器
age = models.IntegerField('年龄', validators=[MinValueValidator(6, message='年龄不能小于6岁'),
MaxValueValidator(100, message='年龄不能大于100岁')])
gender = models.CharField('性别', max_length=1, choices=GENDER_CHOICES)
# 校验邮箱的格式 是否正确
email = models.EmailField('邮箱', unique=True, max_length=254)
# 允许为空
address = models.TextField('地址', blank=True)
执行数据库迁移的两行代码

成功之后刷新数据库中的表 可以看到新建的表

表有了 接着我们给它插入几条测试数据
这里可以采用Django自带的admin后台可视化管理学生数据 在admin.py中写入如下代码
python
from django.contrib import admin
from .models import Student
# 注册Student模型
admin.site.register(Student)
然后在终端输入创建超级管理员的命令
python
python manage.py createsuperuser
# 按提示输入用户名、邮箱、密码
项目启动后 在浏览器中输入 http://127.0.0.1:8000/admin/ 即可访问 输入刚刚创建的用户名 和密码即可


找到要操作的类 表 可以可视化对数据库的操作

可以玩玩里面的操作 我们还是手搓实现 CRUD
web查
首先是查数据 我们先向数据库中手动增加几条数据

python
# 导入模型类
from .models import Student
def show(request):
student = Student.objects.all()
return render(request, 'demo1/show.html', {'students': student})
新建show.html静态模板 这里需要引入一个知识就是模板继承 比如要实现导航栏不变的的情况 每个页面的页面都不一样会造成代码的冗余 而且要是有修改的话 会更加的麻烦 于是写个基本的模板 其它模板继承这个即可
所以新建一个base.html文件名无所谓 记得即可 样式用bootstrap 想要什么样式可以去官网找 Examples · Bootstrap v5 中文文档 v5.3 | Bootstrap 中文网
这里演示的是CDN 在线引入 在html head中引入css js 还有一种将bootstrap下载到本地的
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}学生管理系统{% endblock %}</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
{% block extra_js %}
{% endblock %}
<style>
body {
padding-top: 20px;
background-color: #f8f9fa;
}
.navbar {
box-shadow: 0 2px 4px rgba(0,0,0,.1);
}
.card {
box-shadow: 0 2px 4px rgba(0,0,0,.05);
border: none;
margin-bottom: 20px;
}
.card-header {
background-color: #fff;
border-bottom: 1px solid rgba(0,0,0,.125);
font-weight: 600;
}
.table-hover tbody tr:hover {
background-color: rgba(0,123,255,.05);
}
.badge-gpa {
font-size: 0.9em;
padding: 0.4em 0.8em;
}
.status-active {
color: #28a745;
}
.status-inactive {
color: #dc3545;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white mb-4">
<div class="container">
<a class="navbar-brand fw-bold text-primary" href="">
<i class="bi bi-people-fill me-2"></i>学生管理系统
</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="">
<i class="bi bi-list-ul me-1"></i>学生列表
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">
<i class="bi bi-person-plus me-1"></i>添加学生
</a>
</li>
<li class="nav-item">
<a class="nav-link" href=""
onclick="return confirm('确定要生成示例数据吗?')">
<i class="bi bi-database-add me-1"></i>生成示例数据
</a>
</li>
</ul>
</div>
</div>
</nav>
{% block content %}
{% endblock %}
</body>
</html>
python
{% block content %}
{% endblock %}
# 意思是 在html页面中占个位置 后续有代码可以填充到这个位置
# 上面的JS也是同理
OK 基础模板写好了 我们在show.html页面中继承即可 先将数据写死看一下页面的结构 后面修改即可
python
# 继承模板语法
{% extends "demo1/base.html" %}
# 写页面的主内容
{% block content %}
<div class="row mt-5">
<div class="col-md-7 mx-auto">
<div class="card shadow-sm border-0 rounded-4">
<div class="card-header bg-secondary text-white rounded-top-4">
<h5 class="mb-0">学生信息列表</h5>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-striped table-hover mb-0">
<thead class="table-light">
<tr align="center">
<th scope="col" class="ps-4">姓名</th>
<th scope="col">学号</th>
<th scope="col">年龄</th>
<th scope="col">性别</th>
<th scope="col">邮箱</th>
<th scope="col" class="pe-4">地址</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ps-4">李四</td>
<td>20250002</td>
<td>19</td>
<td>女</td>
<td>lisi@example.com</td>
<td class="pe-4">上海市浦东新区</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
python
# 遍历返回的字典数据 拿到里面的具体的值 django模板的写法就是.取值
{% for i in students %}
<tr align="center">
<td class="ps-4">{{ i.name }}</td>
<td>{{ i.student_id }}</td>
<td>{{ i.age }}</td>
<td>{{ i.gender }}</td>
<td>{{ i.email }}</td>
<td class="pe-4">{{ i.address }}</td>
</tr>
{% endfor %}
完成之后就是这样的效果

OK 继续写增加的页面逻辑
web增
需求是输入字段信息 之后会自动校验 不符合要求的数据不会保存至数据库 并有相应的提示 然后添加完成之后会返回 学生信息列表的页面
路由与视图函数的映射就不说了 这里讲一个新的知识点 就是modelform
大家在写表单的时候,会发现表单中的 Field 和模型中的 Field 基本上是一模一样的,而且表单中需要 验证的数据,也就是我们模型中需要保存的。那么这时候我们就可以将模型中的字段和表单中的字段进行绑定
在app中新建一个forms文件
python
# 导入forms包
from django import forms
# 模型类
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
# 指定是哪个模型
model = Student
# 需要验证的字段 是否满足当时定义的情况
fields = '__all__'
在视图函数中继续写实现逻辑
python
# 导入form
from .forms import StudentForm
def add(request):
# 如果是get请求的话 也就是点击到添加页面来 就返回添加的页面
if request.method == 'GET':
return render(request, 'demo1/add.html')
# post 请求 也就是添加完数据之后点击提交
# 创建一个表单对象 传入post表单中的数据
form = StudentForm(request.POST)
# 判断表单数据是否合法 有效 如果有效 就将数据保存到数据库
if form.is_valid():
form.save()
# 重定向到展示页面
return redirect('/demo1/show')
# 表单数据不合法 则继续返回添加页面
else:
print(form.errors)
return render(request, 'demo1/add.html')
之后继续写前端代码
python
{% extends 'demo1/base.html' %}
{% block content %}
<!-- 学生信息表单卡片 -->
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card shadow-sm border-0 rounded-4">
<div class="card-header bg-primary text-white rounded-top-4">
<h5 class="mb-0">添加学生信息</h5>
</div>
<div class="card-body p-4">
<form action="" method="post">
{% csrf_token %}
<!-- 姓名 -->
<div class="mb-3">
<label for="name" class="form-label fw-medium">姓名</label>
<input type="text" class="form-control rounded-pill border-primary"
id="name" name="name" maxlength="100" required
placeholder="请输入学生姓名">
</div>
<!-- 学号 -->
<div class="mb-3">
<label for="student_id" class="form-label fw-medium">学号</label>
<input type="text" class="form-control rounded-pill border-primary"
id="student_id" name="student_id" maxlength="20" required
placeholder="请输入唯一学号">
<div class="form-text text-muted">学号长度不超过20字符,且唯一</div>
</div>
<!-- 年龄 -->
<div class="mb-3">
<label for="age" class="form-label fw-medium">年龄</label>
<input type="number" class="form-control rounded-pill border-primary"
id="age" name="age" min="6" max="100" required
placeholder="请输入年龄(6-100岁)">
<div class="form-text text-muted">年龄范围:6-100岁</div>
</div>
<!-- 性别 -->
<div class="mb-3">
<label for="gender" class="form-label fw-medium">性别</label>
<select class="form-select rounded-pill border-primary"
id="gender" name="gender" required>
<option value="" selected disabled>请选择性别</option>
<option value="M">男</option>
<option value="F">女</option>
<option value="O">其它</option>
</select>
</div>
<!-- 邮箱 -->
<div class="mb-3">
<label for="email" class="form-label fw-medium">邮箱</label>
<input type="email" class="form-control rounded-pill border-primary"
id="email" name="email" maxlength="254" required
placeholder="请输入邮箱地址">
<div class="form-text text-muted">邮箱需唯一,格式需正确</div>
</div>
<!-- 地址 -->
<div class="mb-4">
<label for="address" class="form-label fw-medium">地址</label>
<textarea class="form-control rounded-3 border-primary"
id="address" name="address" rows="3"
placeholder="选填:请输入学生地址"></textarea>
</div>
<!-- 提交按钮 -->
<button type="submit" class="btn btn-primary w-100 py-2 rounded-pill fs-5">
提交学生信息
</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}


接下来把右上角的两个按钮实现一下 示例数据不实现了
回到定义路由的页面 定义路由的名称
python
path('add/', views.add, name='student_add'),
path('show/', views.show, name='student_show'),
在base.html中 将名称写入即可
python
<a class="nav-link" href="{% url 'demo1:student_show' %}">
<i class="bi bi-list-ul me-1"></i>学生列表
</a>
{% url %} 模板标签:Django 提供的 URL 反向解析功能 路由反转
OK 现在我们来完成改的逻辑
web改
修改就是拿到要修改数据的id 然后通过这个id修改数据
python
urlpatterns = [
path('add/', views.add, name='student_add'),
path('show/', views.show, name='student_show'),
# 定义路由 前端将id传入后端 定义路由的名字
path('update/<int:id>', views.update, name='student_update'),
]
python
def update(request, id):
"""
修改学生信息
:param request:
:param id: 接收前端页面传过来的id
:return:
"""
if request.method == 'GET':
# 根据id查询数据 并提取符合条件的第一条数据
result = Student.objects.filter(id=id).first()
# 创建一个StudentForm表单实例,并将查询到的学生数据(result)作为初始值填充到表单中
form = StudentForm(instance=result)
# 将表单对象传递给模板文件 能够在编辑页面展示出来
return render(request, 'demo1/update.html', {'form': form})
# 如果是post请求 则修改数据
form = StudentForm(data=request.POST)
# 判断表单数据是否合法 有效 和增加的逻辑差不多
if form.is_valid():
# 如果数据合法 则拿到这条数据的id 执行跟新的语法 传入表单验证之后的干净数据
# ** 表示将字典中的数据作为参数传入 字典解包操作
Student.objects.filter(id=id).update(**form.cleaned_data)
return redirect('/demo1/show')
return render(request, 'demo1/update.html', {'form': form})
接下来写静态页面 直接将之前添加数据模板复制过来 修改一下即可
python
{% extends 'demo1/base.html' %}
{% block content %}
<!-- 学生信息表单卡片 -->
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card shadow-sm border-0 rounded-4">
<div class="card-header bg-primary text-white rounded-top-4">
<h5 class="mb-0">修改学生信息</h5>
</div>
<div class="card-body p-4">
<form method="post">
{% csrf_token %}
<!-- 姓名 -->
<div class="mb-3">
<label for="name" class="form-label fw-medium">姓名</label>
<input type="text" class="form-control rounded-pill border-primary"
id="name" name="name"
value="{{ form.instance.name|default_if_none:'' }}">
</div>
<!-- 学号 -->
<div class="mb-3">
<label for="student_id" class="form-label fw-medium">学号</label>
<input type="text" class="form-control rounded-pill border-primary"
id="student_id" name="student_id" maxlength="20" required
value="{{ form.instance.student_id|default_if_none:'' }}">
<div class="form-text text-muted">学号长度不超过20字符,且唯一</div>
</div>
<!-- 年龄 -->
<div class="mb-3">
<label for="age" class="form-label fw-medium">年龄</label>
<input type="number" class="form-control rounded-pill border-primary"
id="age" name="age" min="6" max="100" required
value="{{ form.instance.age|default_if_none:'' }}">
<div class="form-text text-muted">年龄范围:6-100岁</div>
</div>
<!-- 性别 -->
<div class="mb-3">
<label for="gender" class="form-label fw-medium">性别</label>
<select class="form-select rounded-pill border-primary"
id="gender" name="gender" required>
<option value="" disabled>请选择性别</option>
<option value="M" {% if form.instance.gender == 'M' %}selected{% endif %}>男</option>
<option value="F" {% if form.instance.gender == 'F' %}selected{% endif %}>女</option>
<option value="O" {% if form.instance.gender == 'O' %}selected{% endif %}>其它</option>
</select>
</div>
<!-- 邮箱 -->
<div class="mb-3">
<label for="email" class="form-label fw-medium">邮箱</label>
<input type="email" class="form-control rounded-pill border-primary"
id="email" name="email" maxlength="254" required
value="{{ form.instance.email|default_if_none:'' }}">
<div class="form-text text-muted">邮箱需唯一,格式需正确</div>
</div>
<!-- 地址 -->
<div class="mb-4">
<label for="address" class="form-label fw-medium">地址</label>
<textarea class="form-control rounded-3 border-primary"
id="address" name="address" rows="3">{{ form.instance.address|default_if_none:'' }}</textarea>
</div>
<!-- 提交按钮 -->
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{% url 'demo1:student_show' %}" class="btn btn-secondary me-md-2 rounded-pill px-4">取消</a>
<button type="submit" class="btn btn-primary rounded-pill px-4">
更新学生信息
</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{``{ form.instance.字段名|default_if_none:'' }} 来正确获取后端传过来的表单实例的值 没有的话 显示空字符串
还设置了取消的按钮 点击即可返回到列表界面
完成后的效果如下



web删
最后一个删除功能 和编辑的逻辑差不多 拿到数据的id删除即可 然后删除完返回到信息展示列表
python
urlpatterns = [
path('add/', views.add, name='student_add'),
path('show/', views.show, name='student_show'),
path('update/<int:id>', views.update, name='student_update'),
path('delete/<int:id>', views.delete, name='student_delete'),
]
python
def delete(request,id):
"""
删除学生信息
:param request:
:param id: 接收前端页面传过来的id
:return:
"""
Student.objects.filter(id=id).delete()
return redirect('demo1:student_show')
在列表页面 增加删除按钮 以及 路由反转 表头tr中加个操作
python
<td>
<a href="{% url 'demo1:student_update' i.id %}" class="btn btn-primary">编辑</a>
<a href="{% url 'demo1:student_delete' i.id %}" class="btn btn-danger">删除</a>
</td>
效果如下


这样我们就完成了 web页面最基本的CRUD 以上代码还有很多不足以及可以优化的地方
本次的案例分析就到此结束啦 谢谢大家的观看 你的点赞和关注是我更新的最大动力
如果感兴趣的话可以看看我之前的博客
希望对你有帮助