Model、Form、ModelForm 灰太狼 2021-11-30 00:06 224阅读 0赞 本节内容: 1:Model 2:Form 3:Model <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> </td> <td> <div> <div> <code>http:</code> <code>//www</code> <code>.cnblogs.com</code> <code>/wupeiqi/articles/6144178</code> <code>.html 武sir:Form组件</code> </div> <div style="text-align:left;"> <code>http:</code> <code>//www</code> <code>.cnblogs.com</code> <code>/wupeiqi/articles/6216618</code> <code>.html 武sir:Model</code> </div> <div> <code>http:</code> <code>//www</code> <code>.cnblogs.com</code> <code>/wupeiqi/articles/6229414</code> <code>.html 武sir:ModelForm</code> </div> </div> </td> </tr> </tbody> </table> Model ==> 强大的数据库操作,弱小的数据验证。 Form ==>强大的数据验证 ModelForm ===>二者结合,强大的数据验证,适中的数据库操作。在ModelForm是能够封装一个model对象。 ### 1:Model ### 对于Model来说,他的验证是需要自己去创建一个model对象,然后去进行判断 ![复制代码][copycode.gif] model: 针对单一字段 :full_clean 针对多个的字段: clean full_clean -- >字段正则判定 -- >clean方法(钩子) 他是没有最终产物 ![复制代码][copycode.gif] views: ![复制代码][copycode.gif] def fm(request): obj = models.News(title='root') ##full_clean就进行了验证,如果要是有errors的话,就直接报错,所以在进行验证的时候,我们要自己做try判断 obj.full_clean() ##进行model的验证。里面的def clean 方法 obj.save() ##报错 django.core.exceptions.ValidationError: {'__all__': ['title不能是root']} return render(request,"form.html",locals()) ![复制代码][copycode.gif] models: ![复制代码][copycode.gif] from django.db import models from django.core.exceptions import ValidationError class News(models.Model): title = models.CharField(max_length=32) ##验证错误会输出到errors中去 def clean(self): if self.title == "root": raise ValidationError("title不能是root") ![复制代码][copycode.gif] model的源码分析: ![ContractedBlock.gif][] def full\_clean(self, exclude=None, validate\_unique=True): """ Call clean\_fields(), clean(), and validate\_unique() on the model. Raise a ValidationError for any errors that occur. """ errors = \{\} if exclude is None: exclude = \[\] else: exclude = list(exclude) try: self.clean\_fields(exclude=exclude) \#\#\#\#执行单个字段的验证 except ValidationError as e: errors = e.update\_error\_dict(errors) \# Form.clean() is run even if other validation fails, so do the \# same with Model.clean() for consistency. try: self.clean() \#\#\#\#执行clean的方法验证 except ValidationError as e: errors = e.update\_error\_dict(errors) \#\#\#如果错误,把错误添加到errors中 \# Run unique checks, but only for fields that passed validation. if validate\_unique: for name in errors: if name != NON\_FIELD\_ERRORS and name not in exclude: exclude.append(name) try: self.validate\_unique(exclude=exclude) except ValidationError as e: errors = e.update\_error\_dict(errors) if errors: \#\#\#如果有错误,就直接报错了,so 我们要自己去views视图中去判断,try raise ValidationError(errors) ### 2:Form ### 有着强大的验证功能: 具体看源码。 对于Form来说,是当一个请求来了,直接进行post数据的验证,如果是错误会有一个obj.errors的错误对应。 ![复制代码][copycode.gif] Form :有强大的验证 针对单一字段的: full_clean 自定义针对单一字段的: clean_username 针对多个字段的: clean 【or】port_clean (这个是不能出现异常,只能添加异常) is_valid() -- >full_clean () --> -->每个字段的正则,每个字段clean_字段名() -->clean_form -->clean(钩子) -->_post_clean(钩子) 验证后的产物:clean_date 或obj.errors ![复制代码][copycode.gif] **Form中要获取数据库的实时数据:** **两种方式:** <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>第二种方式,虽然是可以用但是它的可定制性差。是需要依赖model的</code> </div> </div> </td> </tr> </tbody> </table> ![1037066-20180524141106514-1091838532.png][] 浏览器中:显示 ![1037066-20180524141304763-1530455949.png][] ## 3:ModelForm ## #### **Model、Form、ModelForm三者的结合:** #### ![复制代码][copycode.gif] 在公司比较大的时候:比如说: models文件是放在A项目中 forms是放在B项目中 froms是没办法导入models中的数据的。 我们就让Form单独的做数据验证,而model就单纯的做数据库操作各司其职是完美的。 但是dajngo还存在了一种叫ModelForm的东西,他是结合了model和Form的功能。 ![复制代码][copycode.gif] #### **Form和ModelForm的继承关系:** #### ![复制代码][copycode.gif] Form: 继承关系: UserForm -- > Form -- >BaseForm ModelForm: 继承关系: NewsModelForm -->ModelForm -->BaseModelForm -->BaseForm 所以modelForm和Form是有同一个祖宗的,Form中的BaseForm的功能,ModelForm也一样可以使用。 ![复制代码][copycode.gif] #### **ModelForm的简单使用:** #### ![ContractedBlock.gif][] model from django.db import models from django.core.exceptions import ValidationError class User\_Type(models.Model): name = models.CharField(max\_length=32) def \_\_str\_\_(self): return self.name class Tags(models.Model): name = models.CharField(max\_length=32) def \_\_str\_\_(self): return self.name class News(models.Model): title = models.CharField(max\_length=32) type = models.ForeignKey(User\_Type,on\_delete=models.CASCADE,blank=True,null=True) tag = models.ManyToManyField(Tags) \#\#验证错误会输出到errors中去 def clean(self): if self.title == "root": raise ValidationError("title不能是root") model ![复制代码][copycode.gif] from django.forms import Form ##Form要继承的 from django.forms import ModelForm ##ModelForm继承 from web import models class NewsModelForm(ModelForm): class Meta: model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的 fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段 def mf(request): if request.method == "GET": obj = NewsModelForm() if request.method == "POST": obj = NewsModelForm(data=request.POST) ##传入进行验证 if obj.is_valid(): #models.News.objects.create(**obj.cleaned_data) ##以前Form的时候添加数据要这样写 obj.save() ##modelform现在可以直接save就可以,save的时候可以保存一对多、多对多的数据 else: print(obj.errors) return render(request, "mf.html", locals()) ![复制代码][copycode.gif] template: \[是不需要执行上面的什么\_\_init\_\_方法、和第二种方法\]直接就可以实时了。 <form action="" method="post"> {% csrf_token %} { { obj.as_p }} <input type="submit"> </form> ![1037066-20180524150515018-1402885409.png][] #### ModelForm的另一个功能:修改 #### urls: <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>re_path(</code> <code>'edit-(\d+).html'</code> <code>,views.edit)</code> </div> </div> </td> </tr> </tbody> </table> views: ![复制代码][copycode.gif] class NewsModelForm(ModelForm): class Meta: model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的 fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段 def edit(request,nid): if request.method == "GET": model_obj = models.News.objects.get(id=nid) ##获取model对象 obj = NewsModelForm(instance=model_obj) else: model_obj = models.News.objects.get(id=nid) obj = NewsModelForm(request.POST,instance=model_obj) ##修改的时候是需要instance 的!如果没有则默认就是增加数据的 if obj.is_valid(): # obj.save() ##他里面的源码默认是commit=True 会帮你第三张表一起修改了。而在django是可以自己手动指定修改的 mobj = obj.save(commit=False) #要是commit为False的话,他会返回一个model的对象、点击commit看源码 mobj.save() ##保存自己表中数据 mobj.save_m2m() ##修改第三张表中的数据,而你要在这二者之间是可以做,一些你想做的事情的 return render(request,"mf.html",locals()) ![复制代码][copycode.gif] template: <form action="" method="post"> {% csrf_token %} { { obj.as_p }} <input type="submit"> </form> #### ModelForm中Meta的详解 #### ![复制代码][copycode.gif] # from web import forms from django.forms import Form ##Form要继承的 from django.forms import ModelForm ##ModelForm继承 from web import models from django.forms import widgets as ws from django import forms from django.forms import fields class NewsModelForm(ModelForm): email = fields.CharField() ##这个会叫把原来的email字段覆盖,变成了CharField的属性验证 pwd = fields.CharField() ##还能够增加一个News中model之外的字段,很有用。的 class Meta: model = models.News ##里面必须要有一个model,因为他是对每个models类做增删改查的 fields = "__all__" ##指定了类,要需要指定要处理哪几个字段 __all__是全部字段 #exclude = ["email",] ##排除某个字段 labels = {"name":"名字","title":"标题"} ##显示字段的label help_texts = {"title":"*"} ##显示字段的help_texts "*"我们代表为必填 widgets = { "name":ws.Textarea(attrs={"class":"c1"}) ##自定义字段标签。和加属性 } error_messages ={ "email":{"required":"必填","invalid":"格式错误"} ##自定义错误提示 } field_classes = { "name":forms.EmailField ##ModelForm的字段是model中的,name在model是CharField的,而我们可以更改他的验证以邮箱格式进行验证 } localized_fields = ("ctime",) ##model中是UTC时间,显示的时候 按本地时间输出 ![复制代码][copycode.gif] #### 动态生成ModelForm表单 #### ![复制代码][copycode.gif] def Dynamic_Model_Form(admin_class,form_change=True): class Meta: model = admin_class.model fields = "__all__" ##排除exclude的字段 admin_class.form_change = False ##用户前端页面是否生成p标签的判断 if form_change: admin_class.form_change = True exclude = admin_class.readonly_fields def __new__(cls,*args,**kwargs): for field_name in cls.base_fields: ##字段都包含在了cls.base_fields中 filed_obj = cls.base_fields[field_name] #添加属性 filed_obj.widget.attrs.update({'class':'form-control'}) ## return ModelForm.__new__(cls) DyModelForm = type("Foo",(ModelForm,),{"Meta":Meta,"__new__":__new__}) return DyModelForm ![复制代码][copycode.gif] 转载于:https://www.cnblogs.com/xyhh/p/10860272.html [copycode.gif]: /images/20211129/7c6b9122b865412dbddd859f2fa890af.png [ContractedBlock.gif]: /images/20211129/fb08d3adc00746eba2f65ca5aa62305f.png [1037066-20180524141106514-1091838532.png]: /images/20211129/62824cfb180146c8bb82f877058eab92.png [1037066-20180524141304763-1530455949.png]: /images/20211129/83ed9a9d2ad040abb2435beb3b67d2aa.png [1037066-20180524150515018-1402885409.png]: /images/20211129/ab58a903514d41639ec63760c71e3039.png
还没有评论,来说两句吧...