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的源码分析:

 

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

原文地址:https://www.cnblogs.com/xyhh/p/10860272.html

时间: 2024-10-09 04:30:15

Model、Form、ModelForm的相关文章

Django使用普通表单、Form、以及modelForm操作数据库方式总结

Django使用普通表单.Form.以及modelForm操作数据库主要应用于增删该查的情景下,流程通用如下,只是实现方式不一样: 进入填写表单页面: 在表单页面填写信息,并提交: 表单数据验证 验证成功,和数据库进行交互(增删改查): 验证成功,页面提示表单填写失败: 一.Django使用普通表单操作数据库 1.html代码: <form action="/add/" method="post" name="addbook"> {%

asp.net Request、Request.Form、Request.QueryString的区别(转)

Request.Form:获取以POST方式提交的数据. Request.QueryString:获取地址栏参数(以GET方式提交的数据). Request:包含以上两种方式(优先获取GET方式提交的数据),它会在QueryString.Form.ServerVariable中都搜寻一遍. 有时候会得到不同的结果.如果仅仅需要Form中的数据,但是使用了Request而不是Request.Form,那么程序将在QueryString.ServerVariable中也搜寻一遍.如果其中有同名的项,

bootstrap源码分析之foRm、navbar

一.表单(Form) 源码文件:_form.scssmixins/_form.scss 1.按层次结构分:form-group -> form-control/input-group/form-static-control -> 各类标签2.Form-group/form-control/input-group/form-static-control之类的容器,分为两种显示方式:block.inline-block.而实现input-group水平用的是table-cell. .input-g

Request、Request.Form、Request.QueryString 用法的区别

Request.Form:获取以POST方式提交的数据. Request.QueryString:获取地址栏参数(以GET方式提交的数据). Request:包含以上两种方式(优先获取GET方式提交的数据),它会在QueryString.Form.ServerVariable中都搜寻一遍. 有时候会得到不同的结果.如果仅仅需要Form中的数据,但是使用了Request而不是Request.Form,那么程序将在QueryString.ServerVariable中也搜寻一遍.如果其中有同名的项,

display:inline、block、inline-block区别

块状元素 在html中 div.p.h1.form.ul和 li就是块级元素.设置display:block就是将元素显示为块级元素. 块状元素特点: 1.每个块级元素都从新的一行开始,并且其后的元素也另起一行.(真霸道,一个块级元素独占一行) 2.元素的高度.宽度.行高以及顶和底边距都可设置. 3.元素宽度在不设置的情况下,是它本身父容器的100%(和父元素的宽度一致),除非设定一个宽度. 内联元素 在html中,span.a.label. strong 和em就是典型的内联元素(行内元素)(

[SAP ABAP开发技术总结]RETURN、STOP、EXIT、CHECK、LEAVE、REJECT

目录导航 声明:原创作品,转载时请注明文章来自SAP师太博客,并以超链接形式标明文章原始出处,否则将追究法律责任!原文出自: 12.21.1.            RETURN.. 110 12.21.2.            STOP. 110 12.21.3.            EXIT. 110 12.21.4.            CHECK. 110 12.21.5.            LEAVE. 111 12.21.5.1.         REJECT. 111 1

HTML、CSS、JavaScript的详细知识点及学习顺序

HTML.CSS.JavaScript的学习顺序一般为html,css,javascript HTML.CSS.JavaScript的详细知识点介绍: 1. HTML 包含文字.图片.视频等. 或为标题加入背景图片.颜色变化,标题字体.比如,就像网页的外衣.样式是表现.2. CSS 边框等.所有这些用来改变内容外观的东西称之为表现. 是用来实现网页上的特效效果.如:鼠标滑过弹出下拉菜单.或鼠标滑过表格JavaScript3. 的背景颜色改变.还有焦点新闻(新闻图片)的轮换.可以这么理解,有动画的

JavaWeb开发中form、ajax提交数据Model转化

JavaWeb开发中form.ajax提交数据Model转化 问题 最近学习MongoDB数据库,作为java开发的我,当然需要做个小的web程序来测试一番了.在html中我采取ajax提交方式,因为我要模拟各种类型的数据,基础数据类型.数组.对象等.然而,最终发现了个不同的地方:Form和ajax提交数据,在HttpServletRequest中尽然参数名有所不同. 数据类型 form ajax 基础数据 para=value para=value 数组 para[]={"aaa",

Django: 之Model、Cookis、Session

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用MySQLdb来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wulaoerdb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(