zoukankan      html  css  js  c++  java
  • Model、Form、ModelForm

    本节内容:

    1:Model

    2:Form

    3:Model

    1
    2
    3
    http://www.cnblogs.com/wupeiqi/articles/6144178.html  武sir:Form组件
    http://www.cnblogs.com/wupeiqi/articles/6216618.html  武sir:Model
    http://www.cnblogs.com/wupeiqi/articles/6229414.html  武sir:ModelForm

    Model ==> 强大的数据库操作,弱小的数据验证。

    Form ==>强大的数据验证

    ModelForm ===>二者结合,强大的数据验证,适中的数据库操作。在ModelForm是能够封装一个model对象。

    1:Model

    对于Model来说,他的验证是需要自己去创建一个model对象,然后去进行判断

    复制代码
    model:
        针对单一字段 :full_clean 
        针对多个的字段: clean
        
        full_clean -- >字段正则判定 -- >clean方法(钩子)
        他是没有最终产物
        
    复制代码

    views:

    复制代码
    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())
    复制代码

    models:

    复制代码
    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")
    复制代码

    model的源码分析:

     View Code

    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的错误对应。

    复制代码
    Form :有强大的验证
        针对单一字段的: full_clean
        自定义针对单一字段的: clean_username 
        针对多个字段的: clean 【or】port_clean (这个是不能出现异常,只能添加异常)
    
        is_valid() -- >full_clean () -->
                                    -->每个字段的正则,每个字段clean_字段名()
                                    -->clean_form -->clean(钩子)
                                    -->_post_clean(钩子)
                                    
        验证后的产物:clean_date 或obj.errors        
    复制代码

    Form中要获取数据库的实时数据:

    两种方式:

    1
    第二种方式,虽然是可以用但是它的可定制性差。是需要依赖model的

     浏览器中:显示

    3:ModelForm 

    Model、Form、ModelForm三者的结合:

    复制代码
    在公司比较大的时候:比如说:
        models文件是放在A项目中
        forms是放在B项目中 
    
    froms是没办法导入models中的数据的。
    我们就让Form单独的做数据验证,而model就单纯的做数据库操作各司其职是完美的。 
    
    但是dajngo还存在了一种叫ModelForm的东西,他是结合了model和Form的功能。
    复制代码

    Form和ModelForm的继承关系:

    复制代码
    Form:
        继承关系:
            UserForm -- > Form -- >BaseForm
    ModelForm: 
        继承关系:
            NewsModelForm -->ModelForm -->BaseModelForm -->BaseForm 
            
            
    所以modelForm和Form是有同一个祖宗的,Form中的BaseForm的功能,ModelForm也一样可以使用。 
    复制代码

    ModelForm的简单使用:

     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

    复制代码
    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())
    复制代码

    template: [是不需要执行上面的什么__init__方法、和第二种方法]直接就可以实时了。 

    <form action="" method="post">
        {% csrf_token %}
        {{ obj.as_p }}
        <input type="submit">
    </form>

    ModelForm的另一个功能:修改

    urls:

    1
    re_path('edit-(d+).html',views.edit)

    views:

    复制代码
    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())
    复制代码

    template:

    <form action="" method="post">
        {% csrf_token %}
        {{ obj.as_p }}
        <input type="submit">
    </form>

    ModelForm中Meta的详解 

    复制代码
    # 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时间,显示的时候 按本地时间输出
    复制代码

    动态生成ModelForm表单 

    复制代码
    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
    复制代码
  • 相关阅读:
    poj 2104 C
    2015 百度之星初赛 1 2 2015ACM/ICPC亚洲区上海站 codeforces 851
    3.10补
    3.9补
    3.8补
    3.6补
    3.5补
    3.4补
    3.3补
    2.35补
  • 原文地址:https://www.cnblogs.com/xyhh/p/10860272.html
Copyright © 2011-2022 走看看