Django的ModelForm,被用来新建或修改一个model对象,使用起来还是很方便的,基本的方法这里不再说明,本文只记录一些我在做项目中有使用到的,有用但零散的东西。
先贴一段完整的ModelForm代码
class ProjectModelForm(ModelForm):
required_css_class = 'required'
def __init__(self, *args, **kwargs):
creater = kwargs.pop("creater")
program = kwargs.pop("program")
super(ProjectModelForm, self).__init__(*args, **kwargs)
self.fields['type'].queryset = SimpleData.objects.filter(dataType = DatayType_enum["project_type"].value)
self.fields['priority'].queryset = SimpleData.objects.filter(dataType = DatayType_enum["priority"].value)
self.fields['owner'].queryset = userWithoutAnonymous
self.fields['country'].initial = Country.objects.get(code = "china")
self.fields['program'].initial = program
self.fields['program'].disabled = True
#开始日期默认为创建当天
self.fields['plan_start_date'].initial = datetime.now()
class Meta:
model = Project
fields = [
'program',
'code',
'plan_start_date','plan_end_date',
'owner',
'type','priority',
'country',
'province',
'description']
widgets = {
'code': Textarea(attrs={'cols': 39, 'rows': 1}),
'plan_start_date':DateInput(attrs={
'type': 'date',
'min': '2020-01-01',
'max': '2050-12-31',
},
format='%Y-%m-%d'),
'plan_end_date':DateInput(attrs={
'type': 'date',
'min': '2020-01-01',
'max': '2050-12-31'
},
format='%Y-%m-%d'
)
}
help_texts={
"code":"如果不填写项目编号,将自动生成唯一编号",
}
labels = {
'product':"产品(可多选)"
}
def clean(self):
cleaned_data = super().clean()
# 对多个字段进行联合验证
plan_start_date = cleaned_data.get('plan_start_date')
plan_end_date = cleaned_data.get('plan_end_date')
if plan_start_date > plan_end_date:
raise forms.ValidationError('开始日期不能大于结束日期')
return cleaned_data
设置初始值
新建对象时,如果想给某个field提供默认值,可以在ModelForm中指定这个field的initial。如新建项目时,country默认选中中国。
self.fields['country'].initial = Country.objects.get(code = "china")
开始日期默认为当天
self.fields['plan_start_date'].initial = datetime.now()
可选范围
对于外键,新建时提供的是一个列表。如owner是一个User模型的外键,那新建时,owner的选项默认是所有用户的一个列表。这时可以通过queryset来指定这个列表的范围,如项目的owner只需要从项目经理这个范围内选择就可以了。
self.fields['owner'].queryset = userWithoutAnonymous
帮助信息
在新建和修改页面中,对某个field提供帮助信息。
在class Meta中的help_texts中指定某个field的帮助信息即可。
help_texts={
"code":"如果不填写项目编号,将自动生成唯一编号",
}
标签值
ModelForm生成的新建页面中,field的标签值默认都为在model中定义的verbose_name。如果想使用其他的标签值,又不想修改model中的verbose_name,在class Meta中可以通过labels来指定。
labels = {
'product':"产品(可多选)"
}
控件属性
在class Meta的 widgets中,可以设置各种html控件的属性。
如charField类型的field,对应的控件是Textarea,即文本框。下面语句可以设置该文本框的列数,行数。
widgets = {
'code': Textarea(attrs={'cols': 39, 'rows': 1}),
}
日期的输入控件可以设置格式如下。
widgets = {
'plan_start_date':DateInput(attrs={
'type': 'date',
'min': '2020-01-01',
'max': '2050-12-31',
},
format='%Y-%m-%d'),
}
控件灰化
有些控件在新建或修改页面中要显示但又不想被修改,可以设置控件灰化,设置disabled为True。
self.fields['program'].disabled = True
必填项增加*号提示
有些field是不能为空的,即blank为False。在新建页面中为了提示,增加*号提示。
在ModelForm定义中增加required_css_class = 'required'
class ProjectModelForm(ModelForm):
required_css_class = 'required'
在html中新增css定义,content为*,color设置颜色为红色。
.required:after {
content: '*';
color:red;
}
数据校验
在ModelForm中定义clean函数,可以在保存前,对数据进行校验,如果校验不满足,可以在页面上进行提示,校验通过才能新建或保存成功。
def clean(self):
cleaned_data = super().clean()
# 对多个字段进行联合验证
plan_start_date = cleaned_data.get('plan_start_date')
plan_end_date = cleaned_data.get('plan_end_date')
if plan_start_date > plan_end_date:
raise forms.ValidationError('开始日期不能大于结束日期')
return cleaned_data