Jun 18, 2011

django 表单,ModelForm

Working with forms
The Forms API

Form

Form 实例在创建的时候就分为 unbound 和 bound,unbound 可以显示 blank 或 default value
unbound Form 实例不能再 bind data
也就是说只有一次机会去 bind data,就是在创建 Form 实例的时候,且其参数为一个 dict

bounded form 不能咋

form.is_valid() 验证数据
不是valid
form.errors

form.cleaned_data 为一个 dict,包含所有数据
form.cleaned_data['subject'] 提取具体 field
只有 is_valid() 为 True,才有form.cleaned_data
def contact(request):
    if request.method == 'POST': # If the form has been submitted...
        form = ContactForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            # Process the data in form.cleaned_data
            # ...
            return HttpResponseRedirect('/thanks/') # Redirect after POST
    else:
        form = ContactForm() # An unbound form

    return render_to_response('contact.html', {
        'form': form,
    })

Behavior of unbound forms

It's meaningless to validate a form with no data, but, for the record, here's what happens with unbound forms:
>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}

表单生成 html 代码

表单可以以 table, p, ul 等方式,输出给 html
f.as_table() 每一个 field 为一行(tr),不带 table tag,用户要自己写
错误信息 ul 和 input 放在一个 td 里面
f.as_p() 每一个 field 为一段
f.as_ul() 每一个 field 为一个 list item (li),不带 ul tag,用户要自己写
错误信息 ul 和 input 放在一个 li 里面


可以看到,如果有错误的话,上面三个函数的输出都包含错误信息。可以通过 f.errors 获得错误信息,输出为 ul。其中每一个有错的 field,其错误信息又是一个 ul

总结,有以下三点
  1. form field 的名称对应html label
  2. form field 的值对应 html input
  3. error 对应 html ul
如果想获得更大的自由,可以单独获得 input 或 error ul
form['first_name'] 可以获得 input
form['email'].errors 可以获得 ul

ModelForm

>>> class ArticleForm(ModelForm):
...     class Meta:
...         model = Article

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

  1. form = ArticleForm()
  2. form = ArticleForm(instance=article) 

这两个都是 unbound forms,但是第2个默认值是 artile.
如果要修改数据库的记录,要用到第二个,可能是因为它包含了 primary key 的信息,这样保存的时候就知道是更新,而不是添加

保存:
ModelForm 除了有 Form 的功能,还有 save()

f.save() #保存到数据库,添加或更新

我们提到过 bounded form 不能再修改数据;如果要在保存之前进行修改,要用到如下命令
new_author = f.save(commit=False) #返回一个 model 实例,可以修改这个实例,之后保存该实例
如果用到这个方法,并且有 many-to-many field,必须再执行 f.save_m2m()

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

0 comments: