Django中的ModelForm与Form

django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm.
关于django中的表单系统有两种:

  • 基于django.forms.Form
  • 基于django.forms.ModelForm

表单API

form.is_bound()

表单有两种状态:绑定和未绑定,使用form.is_bound()来判断.

form.is_valid()

验证表单数据是否合法,返回True或者False

form.errors

表单的错误字典

Form.has_error(field,code=None)

该方法返回一个布尔值,指定一个字段是否具有与特定错误的错误code。如果code是None,它将返回True

form.initial

提供初始值,在表单未绑定的情况下,为表单字段设置初始值.
作为一个有参数的表单, 在实例化一个表单时可以通过指定initial字段来指定表单中数据的初始值. 以这种方式提供的初始值将覆盖表单字段的初始值和附加模型实例的值。

>>> article = Article.objects.get(pk=1)
>>> article.headline
'My headline'
>>> form = ArticleForm(initial={'headline': 'Initial headline'}, instance=article)
>>> form['headline'].value()
'Initial headline'

这些值仅对未绑定的表单显示

>>> f = ContactForm(initial={'subject': 'Hi there!'})

form.has_changed()

检查表单数据是否发生变化

form.clened_data

在每个字段Form类不仅负责验证数据,也为“清洁” -它归到一个一致的格式。这是一个很好的功能,因为它允许以各种方式输入特定字段的数据,总是导致一致的输出。

例如,DateField标准化输入到Python datetime.date对象。不管你是否传递一个字符串中的格式'1994-07-15',一个datetime.date对象,或者一些其他的格式,DateField将始终将它规范化为一个datetime.date,只要它是有效的对象。

一旦你创建一个Form实例与一组数据并验证它,你可以通过它访问干净的数据cleaned_data属性:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}

请注意,任何基于文本的领域-如CharField或EmailField-始终清洁输入Unicode字符串。

如果您的数据并没有被验证通过,该cleaned_data词典只包含有效的字段:

>>> data = {'subject': '',
...         'message': 'Hi there',
...         'sender': 'invalid email address',
...         'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}

当Form有效时,cleaned_data将包括一个键和值 的所有其字段,即使数据没有包括一些可选字段的值。在这个例子中,数据字典不包括用于一个值 nick_name字段,但是cleaned_data包含它,用空值:

>>> from django import forms
>>> class OptionalPersonForm(forms.Form):
...     first_name = forms.CharField()
...     last_name = forms.CharField()
...     nick_name = forms.CharField(required=False)
>>> data = {'first_name': 'John', 'last_name': 'Lennon'}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}

在本例中,cleaned_data为值nick_name设置为空字符串,因为nick_name是CharField和CharField请客空值作为空字符串。每个字段类型都知道它的“空白”的值是多少-例如,对DateField,这是None不是空字符串。

form.as_p()

将表单渲染成<p>标签:

>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></p>
<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required /></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
>>> print(f.as_p())
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></p>
<p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>

form.as_ul()

将表单渲染成形式为一系列的<li>标记,每个<li>含有一个字段。它不包括<ul></ul>,这样就可以在指定的任何HTML属性<ul>的灵活性:

>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>

form.as_table()

跟上面的as_ul()相同,需要自己添加table标签

>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>

设置表单必填行与错误行的样式

关键字:

  • Form.error_css_class
  • Form.required_css_class

用法:

from django import forms
class ContactForm(Form):
    error_css_class = 'error'      #错误行样式在HTML中表示class='error'
    required_css_class = 'required' #必填样式在Html中表示clss=‘required’

然后在css文件中定义error与required类就行了.

配置表单元素的HTML id属性,<label>标签

from.auto_id

>>> f = ContactForm(auto_id=False) #这样在html中表单不包含< label >标签
>>> f = ContactForm(auto_id=True) #在html中表单<label>标签将为每个表单的id
>>> f = ContactForm(auto_id='id_for_%s') #在html中表单<label>标签为id_for_字段id

From.prefix

可以为Django表单添加一个命名空间

>>> mother = PersonForm(prefix='mother')
>>> father = PersonForm(prefix='father')

Field.required

表示该字段为必填 缺省为必填项,如需要指定不为必须

>>> f=forms.CharField(required=True)

Field.label

表示友好的label,表单在页面显示时用到它

name=from.CharField(label="Your name")

Field.help_text

显示字段描述文本

Field.error_message

覆盖默认的错误信息

name = forms.CharField(error_messages={'required':'Please enter your name'}) #覆盖required的默认错误信息

widget

负责渲染网页上的HTML表单

widget.attrs

设置weidget实例样式

class CommentForm(forms.Form):
    name=forms.CharField(widget=forms.TextInput(attrs={'class':'special'}))
    comment = forms.CharField(widget= forms.TextInput(attrs={'size':'40'}))

以上自定义了name字段的输入样式为类 special,comment更改size的大小为40。

内建的widget

TextInput
NumberInput
EmailInput
URLInput
PasswprdInput
HiddenInput
DateInput 日期
DateTimeInput 日期/时间
TimeInput 时间
Textarea
CheckboxInput
Select
NullBooleanSelect 渲染成 unknown,yes,no三个选项
SelectMultiple
RadioSelect
CheckboxSelectMultiple 复选框列表
FileInput 文件上传
SelectDateWidget

ModelForm表单

from django.forms import ModelForm
from myapp.models import Article
class ArticleForm(ModelForm):
    class Meta:
        model = Article  #表单对应的model
        fields = ['pub_date', 'headline', 'content', 'reporter']  #表单中显示的字段,对应models.py中对应的字段

这里需要注意一下:model=article,指定表单对应的model
使用方式:

>>>form =  ArticleForm()
>>>article = Article.objects.get(pk=1)
>>>form = ArticleForm(instance = article)  #赋值instance可以使form表单是可以接受对象的数据

这里需要注意的:instance=article,赋值实例instance,可以使form表单可以接受对象类型的数据

instance 属性,表示与它绑定的模型实例

save()方法

每一个ModelForm都有一个save()方法,这个方法可以根据绑定的form表单创建并且保存一个数据库对象,ModelForm的子类可以接受一个model的子类作为instance的参数,如果存在那么save()方法会更新这个实例,否则会创建一个新的实例

def table_change(request,table_db_name,obj_id):
    if table_db_name in admin.enabled_admins:
    obj = admin.enabled_admins[table_db_name].model.objects.get(id=obj_id)
    field = [field.name for field in admin.enabled_admins[table_db_name._meta.fields]
    if request.method == 'POST':
        form = model_form(request.POST,instance=obj)
        if form.is_valid():
            form.save()
    else:
        form = model_form(instance=obj)
    return render(request,"king_admin/table_change.html",{'form':form})

save(commit=False)

save()方法接受一个commit的参数,其值为True或者False。默认为True。
如果你声明 save(commit=False),那么它就会返回一个还未保存至数据库的对象,这样的话 你可以用这个对象添加一些额外的数据,然后在用save()保存到数据库.

def edit(request,sid):
    edit_obj = get_object_or_404(PointRule,id=sid)
    if request.method == 'POST':
        form = PointRuleForm(request.POST.copy(),instance=edit_obj)
        if form.is_valid():
            point = form.save(commit=False)
            point.update_user = request.user  #在form.save(commit=False时,添加一些表单中未有的数据)
            point.save()
            return redirect('point:index')
        else:
            messages.error(request, u'数据验证错误')
    else:
        form = PointRuleForm(instance=edit_obj)
        return render(request,'point/edit.html',locals())

save_m2m()方法

在save(commit=False)的时候,如果你的model中含有many-to-many的数据模型,那么你将无法使用save()方法去保存数据,只能使用save_m2m()方法来保存.

在为声明save(commit=False),则不用如此保存,用save()就好了...

field字段使用

选择model中所有字段为表单中的字段

__all__

例子:

from django.forms import ModelForm
class AuthorForm(ModelForm)
    class Meta:
         model = Author
         fields='__all__'

剔除指定字段的所有数据 exclude

class PartialAuhorForm(ModelForm):
    class Meta:
        model = Author
        exclude = ['title'] #添加Author model中除了titile字段的所有字段至PartialAuhorForm表单

覆盖字段的默认值

form django.forms import ModelForm, Textarea
form myapp.models import Author
    class AuthorForm(ModelForm):
        class Meta:
            model=Author
            fields=('name','title','birth_date')
            widgets={'name':Textarea(attrs={'cols':80,'rows':20})}
from django.utils.translation import ugettext_lazy as _
 class AuthorForm(ModelForm):
      class Meta:
          model=Author
          fields=('name','title','birth_date')
          labels = { 'name':_('Writer'), }
          help_texts = {'name':_('some useful help text.'),}
          error_messages={ 'name':{'max_length':_("this writer name is too long")} }
原文地址:https://www.cnblogs.com/ccorz/p/Django-zhong-deModelForm-yuForm.html