基于 Django1.10 文档的深入学习(26)—— Creating forms from models 之 基础

Creating forms from models从模型创建表单

ModelForm

class ModelForm[source]
如果您正在构建一个数据库驱动的应用程序,那么可能会有一些形式与Django模型紧密相连。 例如,您可能有一个BlogComment model,并且您想创建一个可以让用户提交注释的表单。 在这种情况下,在forms.py中定义字段类型是多余的,因为您已经定义了模型中的字段。

因此,Django提供了一个帮助类,可以让您从Djangomodel创建一个Form类。

例如:

>>> from django.forms import ModelForm
>>> from myapp.models import Article

# Create the form class.
>>> class ArticleForm(ModelForm):
...     class Meta:
...         model = Article
...         fields = ['pub_date', 'headline', 'content', 'reporter']

# Creating a form to add an article.
>>> form = ArticleForm()

# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)

Field types字段类型

生成的Form类将按照fields属性中指定的顺序为每个指定的模型字段创建一个表单域。

每个模型字段都有相应的默认表单域。 例如,模型上的CharField在表单上表示为CharFieldManyToManyField模型被表示为MultipleChoiceField。 以下是完整的转化列表:

这里写图片描述

正如您所期望的,ForeignKeyManyToManyField模型字段类型是特殊情况:

ForeignKeydjango.forms.ModelChoiceField表示,它是一个ChoiceField,其选项是ModelSet模型。

ManyToManyFielddjango.forms.ModelMultipleChoiceField表示,它是一个MultipleChoiceField,其选项是ModelSet模型。
另外,每个生成的表单域都具有如下属性:

如果模型字段为blank= True,则表单字段中的必填项设置为False。否则,required = True

表单字段的标签设置为模型字段的verbose_name,第一个字符大写。
表单字段的help_text设置为model字段的help_text

如果模型字段有选择集,则表单域的小部件将被设置为选择,选择来自模型字段的选择。选择通常包括默认选择的空白选项。如果需要该字段,则强制用户进行选择。如果模型字段具有blank= True和显式默认值(将初始选择默认值),则不会包括空白选项。

最后,请注意,您可以覆盖用于给定模型字段的表单字段。请参阅覆盖下面的默认字段。


A full example一个完整的例子

考虑这套模型:

from django.db import models
from django.forms import ModelForm

TITLE_CHOICES = (
    ('MR', 'Mr.'),
    ('MRS', 'Mrs.'),
    ('MS', 'Ms.'),
)

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    birth_date = models.DateField(blank=True, null=True)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Book(models.Model):
    name = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ['name', 'title', 'birth_date']

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'authors']

使用这些模型,上面的ModelForm子类将大致相当于此(唯一的区别是save()方法,我们稍后将讨论)。

from django import forms

class AuthorForm(forms.Form):
    name = forms.CharField(max_length=100)
    title = forms.CharField(
        max_length=3,
        widget=forms.Select(choices=TITLE_CHOICES),
    )
    birth_date = forms.DateField(required=False)

class BookForm(forms.Form):
    name = forms.CharField(max_length=100)
    authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

Validation on a ModelForm对ModelForm的验证

验证ModelForm有两个主要步骤:

  1. 验证表单
  2. 验证模型实例

就像正常的表单验证一样,当调用is_valid()或访问errors属性并在调用full_clean()时明确地触发模型窗体验证,尽管通常不会在实践中使用后一种方法。

模型验证(Model.full_clean())从窗体的clean()方法调用之后,从窗体验证步骤触发。

警告

清理过程以各种方式修改传递给ModelForm构造函数的模型实例。 例如,模型上的任何日期字段都将转换为实际的日期对象。失败的验证可能使底层模型实例处于不一致的状态,因此不建议重用它。


覆盖clean()方法

您可以覆盖模型窗体上的clean()方法,以与正常形式相同的方式提供其他验证。

连接到模型对象的模型窗体实例将包含一个实例属性,该属性允许其方法访问该特定模型实例。

警告

ModelForm.clean()方法设置一个标志,使模型验证步骤验证标记为uniqueunique_togetherunique_for_date| month | year的模型字段的唯一性。

如果要覆盖clean()方法并保持此验证,则必须调用父类的clean()方法。


与模型验证的交互

作为验证过程的一部分,ModelForm将调用您的模型上每个字段的clean()方法,该表单上有相应的字段。 如果您排除了任何模型字段,则不会在这些字段上运行验证。 有关现场清理和验证如何工作的更多信息,请参阅表单验证文档。

在进行任何唯一性检查之前,将调用该模型的clean()方法。 有关模型的clean()钩子的更多信息,请参阅验证对象。


关于模型的error_messages的注意事项

在表单域级别或元数据级别定义的错误消息始终优先于模型字段级别定义的错误消息。

仅在模型验证步骤中引发ValidationError时,才会使用模型字段上定义的错误消息,并且在表单级别没有定义相应的错误消息。

您可以通过将NON_FIELD_ERRORS键添加到ModelForm内部Meta类的error_messages字典中来覆盖模型验证引发的NON_FIELD_ERRORS中的错误消息:

from django.forms import ModelForm
from django.core.exceptions import NON_FIELD_ERRORS

class ArticleForm(ModelForm):
    class Meta:
        error_messages = {
            NON_FIELD_ERRORS: {
                'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
            }
        }

The save() method

Every ModelForm also has a save() method. This method creates and saves a database object from the data bound to the form. A subclass of ModelForm can accept an existing model instance as the keyword argument instance; if this is supplied, save() will update that instance. If it’s not supplied, save() will create a new instance of the specified model:

>>> from myapp.models import Article
>>> from myapp.forms import ArticleForm

# Create a form instance from POST data.
>>> f = ArticleForm(request.POST)

# Save a new Article object from the form's data.
>>> new_article = f.save()

# Create a form to edit an existing Article, but use
# POST data to populate the form.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值