使用ModelForm可以大大减少我们的工作量,在model的基础上使用modelform来展示,创建和编辑表单。
form组件的缺点
对于定义的model来说,在自定义form组件的时候还需要重新定义一遍字段,所以ModelForm来了,它较form组件更简单,能做的也更多。
最简单的ModelForm:
1 | from django import forms |
用的时候和form的用法一样。
ModelForm的缺点
虽然ModelForm帮我们简化了操作,但是这样功能会减少,我们在类似CharField中只能写widget,其它关于error_message,label,min_lenght都是不行的。
- 这样的话只能自定义了。
- 或者改变settings中的默认语言为 zh-hans 凑合着用。
添加自定义字段
- 在ModelForm中添加自定义字段同在form中定义字段。
1 | from django import forms |
重写 __init__
方法
- 想把bootstrap的样式应用进去就需要添加,手动添加属性太过繁琐,重写
__init__
方法来批量添加属性。
1 | # froms.py |
增加与编辑
- 利用modelform来增加和编辑数据是很简单的。
- 对于增加只需要实例化一个空的modelform,渲染后在前端填充完毕,后端通过校验后只需要 save 就可以保存这条记录。
- 对于编辑,实例化的时候将需要待编辑的这个model 传给 instance参数,渲染完毕后在前端进行修改,后端实例化
(新数据, 原始数据)
,通过校验后只需要 save 就可以保存编辑。 - 所以增加与编辑的不同之处在于是否使用
instance
1 | def customer_change(request, pk=None): |
note:
- 上面代码可以实现这两个功能的一个前提是: 在
BaseModelForm
的__init__
中instance=None
。
动态创建表单
- 在HTML中,我们只需要遍历ModelForm对象,就可以把所有字段创建出来。
- field.field.required 用来判断这个字段是否是必填字段
1 | <form action="" method="post" class="form-horizontal col-lg-6 col-lg-offset-2" novalidate> |
源码剖析
- 为什么不是
field.required
,而是field.field.required
?
找到 BaseForm
中的 __iter__
方法和 __getitem__
方法
1 | def __iter__(self): |
点击进入get_bound_field
- 其中的self 是 Field 对象。
1 | def get_bound_field(self, form, field_name): |
点击进入 BoundField
1 | class BoundField(object): |
(form, self, field_name) —> (self, form, field, name)
form —> form
self (Field对象) —> field
field_name —> name
self.field = field (self ) (是一个Field)
这里就相当于做了一次缓存,所以,使用 field.field.required才能找到。
例子
实现一个用户注册
相比于以前我们需要将每个字段进行校验,然后在创建这一行数据,ModelForm为我们简化了很多很多!
1 | from django import forms |