Django 中的 forms.ModelForm —— 它是 Django 表单系统和 ORM 的一个“桥梁”,能帮助你快速基于 数据库模型(Model) 自动生成表单,极大减少重复代码。


1. 什么是 ModelForm

  • 普通 Form (forms.Form):完全手写字段,和数据库模型没有直接关系。
  • ModelForm (forms.ModelForm):根据 Django ORM 的 Model 自动生成表单字段,避免重复定义字段。

换句话说,ModelForm = Form + Model 映射
你只需要指定关联的模型 model,Django 会自动:

  1. 根据模型字段生成对应的表单字段;
  2. 自动处理数据校验(包括数据库字段约束,如 max_lengthunique);
  3. 提供 save() 方法,可以直接保存到数据库。

2. 基本用法

模型定义

# models.py
from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=100)author = models.CharField(max_length=50)published_date = models.DateField()price = models.DecimalField(max_digits=6, decimal_places=2)def __str__(self):return self.title

ModelForm 定义

# forms.py
from django import forms
from .models import Bookclass BookForm(forms.ModelForm):class Meta:model = Bookfields = '__all__'   # 或 ['title', 'author']

视图中使用

# views.py
from django.shortcuts import render, redirect
from .forms import BookFormdef create_book(request):if request.method == "POST":form = BookForm(request.POST)if form.is_valid():       # 自动根据模型字段校验form.save()           # 直接保存到数据库return redirect('book_list')else:form = BookForm()return render(request, 'book_form.html', {'form': form})

模板中渲染

<form method="post">{% csrf_token %}{{ form.as_p }}   <!-- 自动渲染为 <p> 包裹的表单控件 --><button type="submit">保存</button>
</form>

3. ModelForm 的关键点

3.1 Meta 类配置

ModelForm 必须包含一个 Meta 内部类,用来定义表单和模型的关系。

常用属性:

  • model:指定关联的模型
  • fields:指定要包含的字段(推荐用列表,不要总用 __all__
  • exclude:排除某些字段
  • widgets:指定表单控件样式(比如 HTML input)
  • labels:自定义字段的标签
  • help_texts:字段提示文字
  • error_messages:自定义错误提示

示例:

class BookForm(forms.ModelForm):class Meta:model = Bookfields = ['title', 'author', 'price']   # 只要部分字段labels = {'title': '书名','author': '作者',}help_texts = {'price': '请输入价格(单位:元)',}error_messages = {'title': {'max_length': '书名太长了!',},}widgets = {'published_date': forms.SelectDateWidget(years=range(2000, 2030)),}

4. 表单数据的保存

4.1 新增

form = BookForm(request.POST)
if form.is_valid():book = form.save()   # 直接保存到数据库

4.2 不立即保存

有时候需要在保存前修改对象,可以用 commit=False

book = form.save(commit=False)
book.price = book.price * 0.9   # 打折
book.save()

4.3 更新已有对象

book = Book.objects.get(pk=1)
form = BookForm(request.POST, instance=book)  # 绑定已有对象
if form.is_valid():form.save()  # 会执行 update 而不是 insert

5. 表单校验

5.1 自动校验

  • 来自模型字段的限制(max_lengthuniqueblank 等)
  • 自动映射到表单校验规则

5.2 自定义校验

可以通过重写 clean_<field>()clean()

方法名中的<field>必须和表单字段名一致;

class BookForm(forms.ModelForm):class Meta:model = Bookfields = '__all__'def clean_price(self):price = self.cleaned_data['price']if price <= 0:raise forms.ValidationError("价格必须大于0!")return pricedef clean(self):cleaned_data = super().clean()title = cleaned_data.get('title')author = cleaned_data.get('author')if title and author and "Django" not in title and author == "某某":raise forms.ValidationError("某某只能写 Django 相关的书!")return cleaned_data

调用顺序:

  • 表单调用了 is_valid(),从而触发了 full_clean() → clean_fields() → clean_<field>()

6. ModelForm 的高级用法

6.1 内联表单(Inline Formset)

Django 提供了 inlineformset_factory,可以在一个表单中编辑主表和子表。
常用于:一个 Author 对应多个 Book 的场景。

from django.forms import inlineformset_factory
BookFormSet = inlineformset_factory(Author, Book, fields=['title', 'price'])

6.2 ModelFormmodelform_factory

如果表单逻辑简单,可以用 modelform_factory 快速生成:

from django.forms import modelform_factory
BookForm = modelform_factory(Book, fields=['title', 'author'])

7. Form vs ModelForm 对比

特点FormModelForm
字段定义手动写每个字段自动从 Model 生成
数据校验需手动写自动结合 Model 的字段规则
保存到数据库需手动处理模型对象保存直接用 save()
使用场景与数据库无关的表单与模型强关联的 CRUD 表单

8. 使用场景总结

✅ 适合:

  • 表单与数据库模型字段高度一致的场景(如后台管理系统、标准 CRUD 表单)
  • 希望快速生成表单,减少重复代码

⚠️ 不适合:

  • 表单和模型差别很大(例如前端提交的数据字段和数据库存储结构完全不一样)
  • 需要复杂的自定义逻辑时,建议继承 forms.Form

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96786.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96786.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/96786.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

补 json的作用

&#xff1a;“我开车直接拧钥匙就能走&#xff0c;为什么还要看仪表盘和用中控台&#xff1f;”直接点击“运行”&#xff0c;就像是汽车的自动驾驶模式。它能帮你开起来&#xff0c;但你不知道它走的是哪条路&#xff0c;油门踩多深。使用 launch.json 配置&#xff0c;就像是…

apache详细讲解(apache介绍+apache配置实验+apache实现https网站)

1.apache HTTP server介绍httpd项目地址:https://httpd.apache.org/ 在Apache2中有三种工作模式&#xff0c;使用者可以根据不同的业务场景来进行选择(1)prefork模式prefork模式是一种老而稳的模式:一个主进程管理者多个子进程&#xff0c;每个子进程单独处理用户请求&#xf…

jajajajajajajava

线程1 线程概念进程:进程指正在内存中运行的程序。进程具有一定的独立性。线程:线程是进程中的一个执行单元。负责当前进程中程序的执行。一个进程中至少有一个线程。如果一个进程中有多个线程&#xff0c;称之为多线程程序。java中的线程采用的是抢占式调度&#xff0c;如果线…

虚拟机CentOS里JDK的安装与环境配置

---本文以JDK17为例---步骤 1&#xff1a;进入/tmp临时目录# 进入临时目录 cd /tmp步骤 2&#xff1a;下载 Java 17 安装包wget https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz步骤 3&am…

mybatis-plus多租户兼容多字段租户标识

默认租户插件处理器的缺陷 在springboot工程中引入mybatis-plus的租户插件TenantLineInnerInterceptor&#xff0c;能简化我们的数据隔离操作&#xff0c;例如各类含租户用户登录权限的rest接口中&#xff0c;不需要再根据登录用户-set租户条件-触发查询&#xff0c;租户插件能…

HBase高级特性(布隆过滤器和协处理器)、列族设计、rowkey设计以及热点问题处理

在阐述HBase高级特性和热点问题处理前&#xff0c;首先回顾一下HBase的特点&#xff1a;分布式、列存储、支持实时读写、存储的数据类型都是字节数组byte[]&#xff0c;主要用来处理结构化和半结构化数据&#xff0c;底层数据存储基于hdfs。 同时&#xff0c;HBase和传统数据库…

redis sentinel 与 clauster 的区别

Redis Sentinel(哨兵)和Redis Cluster(集群)是Redis提供的两种不同的高可用和扩展性解决方案,它们的设计目标和适用场景有显著区别: 1. 核心功能与目标 Redis Sentinel 主要解决主从架构的高可用问题,实现自动故障转移 监控主从节点状态,当主节点故障时自动将从节点提…

MySQL数据库中快速导入大数据sql

1.PwerShell命令页面导入全表数据库 -P3310 指定数据库端口号Get-Content "本地sql文件目录" | .\mysql -u root -p -P 33102.PwerShell命令页面导入单表到数据库 -P3310 指定数据库端口号Get-Content "本地sql文件目录" | .\mysql -u root -p -P 3310 数…

消息类型proto的编写和生成

消息类型proto的编写和生成 代码如下&#xff1a; syntax"proto3"; package xypmq;enum ExchangeType {UNKNOWNTYPE0;DIRECT1;FANOUT2;TOPIC3; };enum DeliveryMode {UNKNOWNMODE0;UNDURABLE1;DURABLE2; };message BasicProperties {string id1;DeliveryMode deliver…

Vuetify:构建优雅Vue应用的Material Design组件库

Vuetify是一个基于Material Design设计规范的Vue.js UI组件库&#xff0c;它提供了80多个精心设计的组件&#xff0c;帮助开发者快速构建美观且功能丰富的企业级应用。核心特性1. 完整的Material Design实现// 所有组件遵循Material Design规范 <v-btn color"primary&q…

SpringBoot 注解深剖:@RequestParam 与 @RequestBody 的终极对决,90% 的开发者都踩过这些坑!

在 SpringBoot 开发中&#xff0c;处理 HTTP 请求参数是我们每天都要面对的工作。而RequestParam和RequestBody这两个注解&#xff0c;就像是我们手中的两把利剑&#xff0c;既能高效解决问题&#xff0c;用不好也可能 "误伤" 自己。作为一名资深 Java 开发者&#x…

【Docker】P2 Docker环境构建准备:MacOS 与 Linux

目录操作系统与 Docker 的兼容性分析Docker 技术本质MacOS 环境下的 Docker 构建1. 安装前准备2. Docker Desktop安装3. 镜像加速配置高级操作&#xff1a;文件共享配置Linux 环境下的 Docker 构建卸载历史版本配置软件源Docker 核心组件安装系统服务配置镜像加速器配置应用配置…

OpenCV 发票识别全流程:透视变换与轮廓检测详解

目录 前言 一、核心技术原理&#xff1a;透视变换与轮廓检测 1. 透视变换&#xff1a;让倾斜发票 “正过来” &#xff08;1&#xff09;什么是透视变换&#xff1f; &#xff08;2&#xff09;透视变换的 5 个关键步骤 2. 轮廓检测&#xff1a;精准定位发票区域 &#x…

并发:使用volatile和不可变性实现线程安全

《Java并发编程实战》中的VolatileCachedFactorizer展示了如何使用volatile和不可变性来实现线程安全。解决了简单缓存实现中可能出现的线程安全问题&#xff0c;同时避免了全量同步带来的性能开销。 场景背景 假设有一个服务&#xff08;如因数分解服务&#xff09;&#xff0…

Linux x86 stability和coredump

1 POSIX pthread_create原理 1&#xff09;fork()、pthread_create()、vfork()对应的系统调用分别是sys_fork()、sys_clone()、sys_vfork()&#xff0c;它们在内核中都是通过do_fork()实现的。 2&#xff09;系统中所有的进程都组织在init_task.tasks链表下面&#xff0c;每个进…

【PyTorch】多对象分割

对象分割任务的目标是找到图像中目标对象的边界。实际应用例如自动驾驶汽车和医学成像分析。这里将使用PyTorch开发一个深度学习模型来完成多对象分割任务。多对象分割的主要目标是自动勾勒出图像中多个目标对象的边界。 对象的边界通常由与图像大小相同的分割掩码定义&#xf…

RabbitMQ---面试题

总结我们所学内容&#xff0c;这里推荐博客进行复习 RabbitMQ---面试题_rabbitmq常问面试题-CSDN博客

MasterGo自动布局(Auto Layout)

自动布局是用来表示 子元素与子元素之间互相影响的一种排版方式,是一种响应式布局技术。一般是将所有元素设计完成后再使用自动布局进行设置。 自动布局就是响应式布局,就是在不同尺寸的手机上宽度不同都应该怎么展示。 一般页面的一级元素使用约束进行相对定位,二级元素及里…

还在重启应用改 Topic?Spring Boot 动态 Kafka 消费的“终极形态”

场景描述&#xff1a; 你的一个微服务正在稳定地消费 Kafka 的 order_topic。现在&#xff0c;上游系统为了做业务隔离&#xff0c;新增加了一个 order_topic_vip&#xff0c;并开始向其中投递 VIP 用户的订单。你需要在不重启、不发布新版本的情况下&#xff0c;让你现有的消费…

使用vllm部署neo4j的text2cypher-gemma-2-9b-it-finetuned-2024v1模型

使用vllm部署neo4j的text2cypher-gemma-2-9b-it-finetuned-2024v1模型 系统环境准备 由于使用的基于 nvcr.io/nvidia/cuda:12.1.1-cudnn8-runtime-ubuntu22.04 的 workbench,需要进行以下准备(其他系统环境可忽略) ldconfig -p | grep libcudnn 找到 libcudnn 的so库,然…