当前位置: 首页 > news >正文

Django Form 与 ModelForm 实战:从留言板 Demo 到图书登记系统

作业背景:第四次作业要求使用 Form 或 ModelForm 完善 quickstart 项目功能。本文基于课程留言板 Demo,扩展实现一个图书登记系统,使用 ModelForm 完成数据验证与数据库存储。

一、前置说明

课程 Demo 中实现了基于forms.Form的留言板功能,包含标题、内容、邮箱三个字段,通过form.cleaned_data手动提取数据。本次作业在此基础上,改用forms.ModelForm实现图书登记功能,体会两者的核心差异。

ModelForm 的核心优势在于字段自动生成、验证规则与模型同步、支持form.save()直接持久化到数据库。

二、项目结构

在原有项目基础上新增library应用,最终目录结构如下:

mysite/ ├── library/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py # 新增:ModelForm 定义 │ ├── models.py # 新增:Book 模型 │ ├── urls.py # 新增:应用路由 │ └── views.py # 新增:图书登记视图 ├── mysite/ │ ├── __init__.py │ ├── settings.py # 修改:注册应用、配置模板 │ ├── urls.py # 修改:包含 library 路由 │ └── wsgi.py ├── templates/ │ └── book_form.html # 新增:模板文件 ├── manage.py └── db.sqlite3

三、详细操作步骤

步骤 1:创建应用

在项目根目录下执行:

cd mysite python manage.py startapp library

步骤 2:注册应用并配置模板目录

修改mysite/settings.py,在INSTALLED_APPS列表末尾追加'library'

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'library', ]

确认TEMPLATES配置中DIRS包含全局模板路径:

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]

步骤 3:定义数据模型

修改library/models.py,定义Book模型:

from django.db import models class Book(models.Model): title = models.CharField(max_length=100, verbose_name='书名') author = models.CharField(max_length=50, verbose_name='作者') publish_date = models.DateField(verbose_name='出版日期') price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格') introduction = models.TextField(blank=True, verbose_name='简介') contact_email = models.EmailField(verbose_name='联系邮箱') created_at = models.DateTimeField(auto_now_add=True, verbose_name='登记时间') class Meta: verbose_name = '图书' verbose_name_plural = '图书' ordering = ['-created_at'] def __str__(self): return self.title

执行数据库迁移命令:

python manage.py makemigrations python manage.py migrate

步骤 4:创建 ModelForm

library目录下新建forms.py

from django import forms from .models import Book class BookForm(forms.ModelForm): class Meta: model = Book fields = ['title', 'author', 'publish_date', 'price', 'introduction', 'contact_email'] labels = { 'title': '图书名称', 'author': '作者姓名', 'publish_date': '出版日期', 'price': '定价 (元)', 'introduction': '内容简介', 'contact_email': '联系邮箱', } error_messages = { 'title': { 'required': '书名不能为空', 'max_length': '书名最长不能超过100个字符', }, 'author': { 'required': '请填写作者姓名', }, 'price': { 'required': '请输入图书价格', 'invalid': '请输入有效的数字', }, 'contact_email': { 'required': '请填写联系邮箱', 'invalid': '邮箱格式不正确', } } widgets = { 'publish_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}), 'introduction': forms.Textarea(attrs={'rows': 4, 'placeholder': '请输入图书简介...', 'class': 'form-control'}), 'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入书名'}), 'author': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入作者'}), 'price': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}), 'contact_email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'example@email.com'}), } def clean_price(self): price = self.cleaned_data.get('price') if price is not None and price < 0: raise forms.ValidationError('价格不能为负数') return price

步骤 5:编写视图

修改library/views.py

from django.shortcuts import render from django.http import HttpResponse from django.views.decorators.http import require_http_methods from .forms import BookForm @require_http_methods(['GET', 'POST']) def book_register(request): if request.method == 'GET': form = BookForm() return render(request, 'book_form.html', context={'form': form}) else: form = BookForm(request.POST) if form.is_valid(): book = form.save() return HttpResponse( f"图书登记成功<br>" f"书名:《{book.title}》<br>" f"作者:{book.author}<br>" f"价格:¥{book.price}<br>" f"邮箱:{book.contact_email}" ) else: return render(request, 'book_form.html', context={'form': form})

步骤 6:配置路由

修改项目级路由mysite/urls.py

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('book/', include('library.urls')), ]

library目录下新建urls.py

from django.urls import path from . import views urlpatterns = [ path('', views.book_register, name='book_register'), ]

步骤 7:编写模板

在项目根目录(与manage.py同级)创建templates文件夹,并在其中新建book_form.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>图书登记</title> <style> body { font-family: "Microsoft YaHei", Arial, sans-serif; max-width: 500px; margin: 50px auto; background: #f5f5f5; } .container { background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h2 { text-align: center; color: #333; margin-bottom: 25px; } .form-group { margin-bottom: 18px; } label { display: block; margin-bottom: 6px; font-weight: bold; color: #555; } input, textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; } input:focus, textarea:focus { border-color: #4CAF50; outline: none; } .errorlist { color: #d32f2f; margin: 5px 0 0 0; padding: 0; list-style: none; font-size: 13px; } button { width: 100%; padding: 12px; background: #4CAF50; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; margin-top: 10px; } button:hover { background: #45a049; } </style> </head> <body> <div class="container"> <h2>图书登记系统</h2> <form method="post" action=""> {% csrf_token %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {{ field }} {% if field.errors %} <ul class="errorlist"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </div> {% endfor %} <button type="submit">提交登记</button> </form> </div> </body> </html>

步骤 8:运行项目

执行开发服务器:

python manage.py runserver

访问http://127.0.0.1:8000/book/即可看到图书登记页面。

四、核心知识点对比

Form 与 ModelForm 的本质区别

forms.Form需要开发者手动声明每一个字段,手动编写视图中的数据保存逻辑,适合不存入数据库的场景,例如搜索框、联系表单。

forms.ModelForm通过Meta类中的modelfields自动映射模型字段,验证规则继承自模型定义,通过form.save()一行代码即可完成数据库持久化,适合所有需要与数据库交互的增删改场景。

三种验证层级

第一层级是字段参数验证,通过min_lengthmax_lengthrequired等参数控制,在字段定义时完成。

第二层级是单字段自定义验证,通过clean_字段名()方法实现,例如本文中对价格负数的检查。

第三层级是整表联合验证,通过重写clean()方法实现,适用于多个字段之间存在逻辑关联的场景,例如确认密码是否一致、结束日期不能早于开始日期等。

五、复习建议

第一,将本文的BookFormModelForm改写为Form版本,手动定义所有字段并编写视图中的保存逻辑,体会两者的代码量差异。

第二,在模板中尝试手动渲染单个字段而非循环渲染,掌握form.titleform.title.errorsform.title.label_tag的用法。

第三,新增一个isbn字段,要求必须为 13 位纯数字,通过clean_isbn()方法实现正则验证。

第四,进入 Django Admin 后台确认数据是否成功写入数据库,理解form.save()背后的 ORM 操作。

六、总结

本次作业基于课程留言板 Demo,通过 ModelForm 实现了图书登记功能,覆盖了模型定义、表单验证、模板渲染、数据持久化的完整流程。ModelForm 的最大价值在于减少重复代码,使表单验证与模型约束保持同步,是 Django 实际开发中的首选方案。

后续可以继续在此项目基础上扩展:添加图书列表页、编辑功能、删除功能,逐步完善为一个完整的 CRUD 应用。

http://www.jsqmd.com/news/674287/

相关文章:

  • 【Dify企业级权限管控实战白皮书】:20年安全架构师亲授RBAC+ABAC双模配置落地五步法
  • 【Dify权限审计黄金标准】:覆盖12类生产环境异常行为的实时告警配置模板(含YAML源码)
  • 宝塔面板如何给公司不同部门的非技术管理员分配特定网站操作权限
  • 韩国浦项科技大学研究团队的“导演思维“
  • 量子纠错条件中 纠错量子操作 R 的分析
  • 全球半导体展会深度解析:为何CSEAC 2026是行业必争之地 - 品牌2026
  • 如何处理SQL大型数据表JOIN超时_分批查询与临时表存储方案
  • **张量核心驱动下的编程语言革新:从PyTorch到自定义DSL的实践与思考**在深度学习迅猛发展的今天,*
  • 2026年质量好的采购预算系统优选公司推荐 - 行业平台推荐
  • 计算机毕业设计:Python农产品价格分析与智能推荐平台 Flask框架 矩阵分解 数据分析 可视化 协同过滤推荐算法 深度学习(建议收藏)✅
  • 终极开源光学材料数据库实战指南:3000+材料折射率一键查询
  • 014、隐私增强技术:零知识证明与混合网络在网关中的应用
  • 国内半导体全产业链展会推荐|全景覆盖国内上下游优质展会 - 品牌2026
  • VAE与扩散模型的reconstruction–generation dilemma
  • R 4.5低代码分析工具开发最后窗口期:官方确认2025Q2起停用legacy builder API,你还在用R 4.4兼容模式?
  • SVG 文本:设计与实现详解
  • 国内半导体展推荐:精选半导体展打造产业对接新场景 - 品牌2026
  • Agent 真正难的地方,不是更聪明,而是先学会“被管住”
  • 5G/6G毫米波设计必看:如何用信道建模参数(RMS时延扩展、K因子)指导你的系统设计?
  • 2026,从“发券”到“发卡”:当外卖折扣变成一门关于“用户关系”的长期生意
  • 内容运营的配图噩梦:我是怎么用工具批量给文章插入图片解决的
  • 如何记录SQL最后一次登录时间_利用触发器自动更新字段
  • 无需编程!KH Coder:让文本数据开口说话的神奇工具
  • React 离线数据同步:基于逻辑时钟(Logical Clock)的 React 本地存储与云端冲突解决算法
  • 大师之上,再造大师:玲珑轮胎“三个向上”战略的深度解码
  • 不同PHP版本对CPU性能有影响吗_硬件与PHP版本匹配建议【说明】
  • 【车载AI落地实战指南】:Dify低代码构建高可靠问答系统,3天完成POC验证(附车企实测数据)
  • Claude Code 启动失败修复指南
  • 如何彻底释放华硕笔记本的隐藏性能?G-Helper轻量控制工具全解析
  • 企业网站设计|网站建设公司哪家好?2026十家网站制作公司深度盘点