一次model.form的使用记录,配合form钩子的过程
在写信息采集功能的时候,需要添加资产信息,使用modelform组件减少工作量
官网介绍:版本1.9.https://docs.djangoproject.com/en/1.9/ref/forms/models/
对应关系,modelform会把model装换成form的对应字段(每个模型字段都有一个对应的默认表单字段):
对应关系如下表:
外键,和多对多比较特殊(是queryset的形式):
外键对应的模型是:ChoiceField
多对多对应的是:MultipleChoiceField
默认的情况下,对应关系生成后:
模型有blank=True
约束的话,form表单的required会设置成False,即不会进行非空校验。
表单字段的标签被设置为模型字段的verbosename,第一个字符大写。
表单字段的helptext被设置为model字段的helptext。
我的使用记录,钩子字段的解释
model.model
class Asset(models.Model): sin = models.CharField(max_length=64,blank=True,null=True)#sin号 asset_choic = ( (1,"网络设备"), (2,"服务器"), (3,"机柜"), (4,"其他"), u_count = models.CharField('位置(几u到几u)',max_length=16,) #大小
modelform
from django.forms import ModelForm from django.forms import widgets from django.core.exceptions import ValidationError class AddAsset(ModelForm):
#下方为钩子,跟form中的钩子一致,需要clean_开头,ValidationError抛出你定义的错误信息 def clean_u_count(self): u_count = self.cleaned_data.get('u_count') if u_count: if len(u_count) < 6 and "-" in u_count : return u_count else: raise ValidationError('请按格式填写,xx-xx,xx为数字') class Meta: #Meta元数据 model = Asset #关联哪张表 #fields = "__all__" 这个显示Asset中所有的字段 #exclude =['xxx'] 指定的列不会显示,实例化时不会初始化,在save()中也不会出现数据 fields = ['types','hostname','sin', 'price','status','server_ipmi', 'ip','u_count','idc','cabinet','bussins','contact' ] widgets = { #widgets允许你自定义标签例如: 'hostname': Textarea(attrs={'cols': 80, 'rows': 20}), #model.form会自动生成id ;id_字段, } labels = { #标签,自定义标签 'sin':'sn号', 'u_count':'u数范围', } error_messages = { #自定义错误信息 'idc':{ 'required':'idc机房不能为空(请选择机房)', },} #localized_fields = ('birth_date',) #本地化,例如你取出数据库的时间,会根据setting中的配置 #转化成本地时间,如果localized_fields = '__all__' 所有的字段豆浆本地化
views中的大致操作:
obj2 = obj1(request.POST) #obj为你的modelform if obj2.is_valid(): print('SSSSSS2') obj2.save() else: res2 = obj2.errors.as_data() print(res2) '''{'hostname': [ValidationError(['This field is required.'])], 'u_count': [ValidationError(['This field is required.'])], 'idc': [ValidationError(['idc机房不能为空(请选择机房)'])], 'cabinet': [ValidationError(['This field is required.'])], 'bussins': [ValidationError(['This field is required.'])], 'contact': [ValidationError(['This field is required.'])]}''' #as_data出来是一个类似列表的形式,可以进行操作
NON_FIELD_ERRORS字段
在表单字段级或表单元级定义的错误消息总是优先于模型字段级别定义的错误消息。
通过在ModelForm的内部元类的errormessages词典中添加nonfielderrors键来覆盖由模型验证所引起的错误的错误消息:
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.", } }
save()方法:
有两种情况:如果提供了instance关键字会进行更新操作,如果没有则会进行创建操作。
>>> 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()
save() 中的commit字段()
这个字段很有用,他可以让你保存你save()的对象,先不必写入数据库,你可以先对他进行更改,添加属性,然后在存入数据库。
官方解释:
save()方法接受一个可选的提交关键字参数,它接受True或False。如果您用commit=False调用save(),那么它将返回尚未保存到数据库的对象。在这种情况下,由您在生成的模型实例上调用save()。如果您想在保存对象之前对其进行定制处理,或者如果您想要使用一个专门的模型保存选项,那么这是非常有用的。默认情况下save(commit=True)。
save(commit=False)实例:
# Create a form instance with POST data. >>> a = Author() >>> f = AuthorForm(request.POST, instance=a) # Create and save the new author instance. There's no need to do anything else. >>> new_author = f.save()
save_m2m()方法:
save(commit=False)在处理复杂的多对多关系不好使
这个方法在满足以下条件的时候使用:
1.多对多关系
2.你需要添加额外的属性
3.save(commit=False)
# 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()
大致的思路,以及小坑
在写这个信息处理的时候,分为查询(包括修改),和添加操作,不在一个界面上,都需要进行验证,所以都使用AddAsset这个modelform进行验证,然而前端传过来的数据,只传过来修改的数据了,有的数据为空,所以有又回到前端,把所有数据包括没改的也发过来了。(找了好一会。。)