Django——form组件和ModelForm

本文详细介绍了如何在Django中使用form组件和ModelForm实现书城的增删改查功能。从构建模型、数据库迁移,到使用admin模块录入数据,再到通过forms组件和ModelForm创建表单,包括视图、模板的编写和错误处理。重点讲解了ModelForm的使用,包括instance参数、POST请求处理、模板改写和元类属性设置优化。同时,文章还探讨了Django请求处理流程,帮助理解form组件在实际项目中的应用。

Django——form组件和ModelForm

一、原生form实现书城增删改查

1、构建模型并完成数据库迁移

(1)构建书城模型
from django.db import models

# Create your models here.
# 创建一个图书管理系统的模型


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)   # 8个有效数,两个浮点
    date = models.DateField()
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
    authors = models.ManyToManyField("Author")

    def __str__(self):
        return self.title


class Publish(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name
models.py
(2)数据库迁移
$ python3 manage.py makemigrations
$ python3 manage.py migrate

2、运用admin模块录入数据

from django.contrib import admin

# Register your models here.
from .models import *


admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Publish)
admin.py

  创建超级用户:

manage.py@formsDemo2 >  createsuperuser
Username (leave blank to use 'hqs'):  yuan
Email address:  
Warning: Password input may be echoed.
Password:  yuan1234
Warning: Password input may be echoed.
Password (again):  yuan1234
Superuser created successfully.

3、录入作者、出版社、书籍信息

  

4、代码

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from app01 import views


urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^books/$', views.book),
    url(r'^books/add', views.addbook),
    url(r'^books/edit/(\d+)', views.editbook),
]
urls.py
from django.shortcuts import render, redirect

# Create your views here.
from .models import *


def book(request):
    book_list = Book.objects.all()

    return render(request, 'books.html', locals())


def addbook(request):
    if request.method == "POST":
        title = request.POST.get("title")
        price = request.POST.get("price")
        date = request.POST.get("date")
        publish_id = request.POST.get("publish_id")
        # getlist(): Return the list of values for the key.
        author_pk_list = request.POST.getlist("author_pk_list")

        # 取到用户输入的书籍信息后添加到数据库Book表中
        book_obj = Book.objects.create(title=title, price=price, date=date, publish_id=publish_id)

        # 直接绑定主键,将作者对象添加到这本书的作者集合中
        book_obj.authors.add(*author_pk_list)

        return redirect("/books/")

    publish_list = Publish.objects.all()
    author_list = Author.objects.all()

    return render(request, "addbook.html", locals())


def editbook(request, edit_book_id):
    if request.method == "POST":
        title = request.POST.get("title")
        price = request.POST.get("price
<think>我们正在讨论Django中的FormModelForm。根据引用内容,我们可以总结如下: 1. **Form类**:需要手动定义每个字段,适用于不与数据库模型直接绑定的表单。例如: ```python from django import forms class UserForm(forms.Form): username = forms.CharField(max_length=50) email = forms.EmailField() password = forms.CharField(widget=forms.PasswordInput) ``` 这里,我们为用户名、邮箱密码分别定义了字段,并指定了字段类型参数(如最大长度、控件类型等)[^1]。 2. **ModelForm类**:基于模型(Model)自动生成表单字段,适用于直接与数据库模型交互的表单。例如: ```python from django.forms import ModelForm from .models import Level # 假设有一个Level模型 class LevelModelForm(forms.ModelForm): class Meta: model = models.Level fields = ['title', 'percent'] ``` 这里,我们只需要在Meta类中指定关联的模型需要包含的字段,ModelForm会自动根据模型字段生成表单字段[^3]。 ### 主要区别: - **字段定义**:Form需要手动定义每个字段;ModelForm通过关联模型自动生成字段。 - **数据库操作**:Form需要手动处理数据保存到数据库;ModelForm可以直接调用`save()`方法将数据保存到关联的模型实例中。 - **代码复用**:ModelForm可以复用模型的字段定义(如字段类型、验证规则等),避免重复代码。 - **验证**:两者都提供表单验证,但ModelForm还会根据模型字段的约束(如唯一性、外键等)进行验证。 ### 使用场景: - 当表单数据不需要直接保存到数据库或涉及多个模型时,使用Form。 - 当表单直接对应一个模型(如创建或更新模型实例)时,使用ModelForm更高效。 ### 示例:ModelForm的日期字段处理 引用[2]展示了如何在ModelForm中自定义日期字段的控件: ```python from django import forms from django.forms import widgets class BookForm(forms.Form): date = forms.DateField(widget=widgets.TextInput(attrs={'type':'date'})) ``` 但在ModelForm中,我们可以更简洁地实现: ```python class BookModelForm(forms.ModelForm): class Meta: model = Book # 假设有一个Book模型 fields = ['date'] widgets = { 'date': forms.DateInput(attrs={'type': 'date'}) } ``` ### 总结: | 特性 | Form | ModelForm | |--------------|---------------------------------|------------------------------------| | 字段定义 | 手动定义每个字段 | 根据模型自动生成字段 | | 数据库操作 | 需手动处理数据保存 | 可直接使用`save()`方法保存 | | 适用场景 | 独立表单、复杂表单(多模型) | 直接关联单一模型的表单(增删改查) | | 代码复用 | 低(重复定义字段) | 高(复用模型字段定义) | §§相关问题§§ 1. 如何在Django中自定义表单字段的控件? 2. ModelForm的save()方法有哪些参数用法? 3. 如何利用ModelForm实现更新模型实例? 4. 在Django中如何同时处理多个ModelForm? 5. 如何为ModelForm添加额外的验证逻辑?</think>### Django FormModelForm 的区别 在 Django 中,`Form` `ModelForm` 都是用于处理表单数据的核心组件,但它们的定位使用场景有显著差异: #### 1. **Form 类(基础表单)** - **手动定义字段**:需要显式声明每个字段及其类型 - **独立于模型**:不直接关联数据库模型 - **适用场景**:非数据库操作的表单(如搜索框、联系表单)或需自定义逻辑的复杂表单 ```python from django import forms class UserForm(forms.Form): username = forms.CharField(max_length=50) # 手动定义字段 email = forms.EmailField() password = forms.CharField(widget=forms.PasswordInput) # 自定义控件 ``` > 特点:完全控制字段逻辑,但需重复编写模型已有的验证规则[^1]。 #### 2. **ModelForm 类(模型表单)** - **自动生成字段**:基于 Model 定义自动创建表单字段 - **深度集成 ORM**:直接关联数据库模型,支持快速 CRUD 操作 - **适用场景**:直接对应数据库模型的增删改查操作 ```python from django.forms import ModelForm from .models import Book # 关联模型 class BookModelForm(ModelForm): class Meta: model = Book # 指定关联模型 fields = ['title', 'author', 'publish_date'] # 自动生成字段 widgets = { 'publish_date': forms.DateInput(attrs={'type': 'date'}) # 可覆盖默认控件 } ``` > 特点:减少重复代码,自动继承模型的验证规则(如 `unique=True`),支持 `form.save()` 直接保存到数据库[^3]。 --- ### 核心对比总结 | 特性 | Form | ModelForm | |---------------------|---------------------------------|-------------------------------| | **字段定义** | 手动声明每个字段 | 根据模型自动生成 | | **数据库关联** | 无直接关联 | 直接绑定模型,支持 `save()` | | **代码量** | 较多(需重复定义验证规则) | 较少(复用模型约束) | | **验证逻辑来源** | 自定义规则 | 自动继承模型字段约束[^3] | | **典型使用场景** | 独立表单/复杂逻辑 | 模型增删改查操作 | #### 关键区别示例 ```python # 使用 ModelForm 保存数据(一行代码完成数据库操作) book_form = BookModelForm(request.POST) if book_form.is_valid(): book_form.save() # 直接保存到数据库 # 使用 Form 需手动处理数据 user_form = UserForm(request.POST) if user_form.is_valid(): # 需手动创建模型实例并赋值 User.objects.create( username=user_form.cleaned_data['username'], email=user_form.cleaned_data['email'] ) ``` --- ### 何时选择? - 选择 **`Form`** 当: - 表单字段与数据库模型不完全对应 - 需要高度自定义验证逻辑(如跨模型验证) - 构建非数据库操作的表单(如密码重置) - 选择 **`ModelForm`** 当: - 表单直接映射单个模型(如后台管理) - 需要快速实现模型的 CRUD 功能 - 避免重复定义模型已有的字段约束[^3] > 最佳实践:优先使用 `ModelForm` 处理模型相关表单,仅在需要特殊逻辑时使用 `Form`[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

休耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值