返回总目录页

Django中form组件相关

 

 

 

 1、sweetalert插件

使用甜蜜弹出框插件:

导入这个js:

复制代码使用:

即可正常显示好看的弹出框:

也可以下载下来这个js插件,本地导入使用:

 

2、使用ajax,和后端交互删除后端和前端的记录,局部刷新页面,不刷新整个页面

要删除谁,前端传递点击删除对象的id,

通过ajax获取要删除的对象,并将对象的id和要发送的url拼接成ajax的url,然后在路由中匹配 

匹配到要删除的对象id(pk),到对应的数据库查找并删除记录,然后发送删除成功的状态,

 

 前端ajax成功回调函数中,判断返回字典的状态键,如果成功,就获取到要删除标签的父标签,然后执行删除这条记录的操作。

 

3、form组件功能 

前端页面:

点击注册发送post请求,后端拿到POST的数据对用户名长度检验,不够长就给前端模板的用户名框后面的error渲染指定提示信息:

 

现在使用Django给我们提供的校验方法:

首先导入 forms类,然后在视图函数中定义一个子类,里面定义两个类变量,使用froms模块中的CharField,使用这个类,会在前端html渲染生成以这个字段为label的input输入框

实例化我们写的一个表单类,把这个表单对象渲染进前端页面返回给浏览器

 前端页面使用这个form对象,将它作为p标签渲染在指定的form表单位置中,

这样前端就能展示出来我们写的这个类。

使用这个类,在渲染页面时会生成了如下的两个p标签,p标签下是label和input,其它设置如下:

修改自定义的类生成的label标签的内容,在页面中显示我们想要的标签名字

 

如下密码也是明文,因为它们生成的都是text类型input框:

 使用widget,修改input使用的类型为密码input类型

 这样就修改了生成的input的类型:

 

 

在类中指定长度:

如果你输入的内容小于6就会给你提示:

它在input标签中生成了这个属性,这是在前端进行的一个校验

下面实验先不要前端进行校验,将这个最小长度属性取消掉,可在form表单中添加novalidate属性,这样即使存在最小长度属性也会不生效,用户名就没有限制长度了。

 

##使用errors,将错误信息渲染在页面上。对象.as_p是使用这个自定义的对象,让它生成input标签。对象.errors是渲染错误。前面生成input标签是get请求,而显示错误信息的时候是post请求,又要实例化另一个form对象

在视图函数中如果是post请求,那么就再实例化自定义的类,并且关键字传参data给这个实例,值是POST请求中的键值对。然后对这个对象使用.is_valid()方法,判断传进去的参数是否有效,有效返回true。然后返回前端数据。第一次get请求注册页面的时候是个空的没有传检验内容的对象,后面的post重新创建的对象是一个新的对象,会覆盖前面get创建的对象

 当什么都不填,点击注册时报错如下:使用对象.errors这样就可以查看到1,2处单个标签显示的错误。3处是所有的错误

当使用小于6个字符的时候报错如下,这跟前端的长度校验一样

form组件的作用:

 

使用form组件的ChoiceField生成下拉框。类中关键字参数choices,值是元组中有元组,元组中的元组两个值,前做option的值,后做显示内容,而键是渲染在select的name上的字段:

生成form多了一个属性了:

前端页面渲染会生成所有字段:

如下就是生成的下拉框。方便但是可定制化比较差

 

可以点取对应的值放在我们需要的模板上   对象.字段获取的是username这个input标签,然后再.取参数(label),label的for属性就用username的id,这样就关联起来了

 

在字段下显示它的错误信息:对象.字段表示这个字段     再.错误就是字段的错误了

再在浏览器上不写内容点击注册,这样就校验显示错误了。这是错误列表,因为一个字典可能有多个错误

不过多少个错误我们只需要显示一个就够了,再加一个.0,取列表第一个错误

取第一个错误生成的就是字符串:

这样就是另外一个错误:

下面是提供默认值:

它是设置成了value

注册错误提示想要修改:

 自定义错误信息,对应参数不满足就使用该字段对应错误信息的值

将下拉框改成redios,还有其他类型转换把

 

改变类,单选变多选:

前端代码复制一份修改一下,变成hobby:

源码中含有的字段:

想要将这个多选框里的数据来自数据库:

生成数据库内容:

导入类,让它等于从数据库中查出来的数据。内容需要是元组,所以使用values_list

数据库中再添加一个它,页面没有刷新出新添加的乒乓球:刷新页面也出不来

这是因为choices所在的类只加载一次,后面创建的对象都是在此基础上创建用的还是之前的数据。修改了字段是从数据库中获取数据,

 可以在下面添加init方法,init中每次创建对象都重新赋值一下这个变量,这样每次创建对象都是从数据库拿到的最新数据,而不是只加载一次类变量的数据。fields里面存的都是类变量=xx的键值对   ,self.fields['hobby']拿到的是hobby这个对象。再.里面的属性获取的是属性的值

这样的话,每次在浏览器刷新页面,多选框都会从数据库拿到最新的数据。

 也可以用如下的方法,后面的就是qs类型

 

自定义校验器

 

 

导入自定义一个校验器,并放到某个字段的validators里面

 

把错误.0去掉0,获得所有错误,把这条错误放到前面了。

如果符合校验规则就没有错了。

 电话校验框

添加一个电话输入框,并进行手机号校验:

首先导入正则校验器

在电话的字符字段里添加校验参数。此处添加校验器,校验器是正则校验器。

正则校验器是一个类。第一个参数就是正则,第二个是错误消息提示

这样的话在电话字段上添加的正则装饰器,实例化一个对象,添加正则匹配以及匹配不成功的错误提示

正确的没有错误提示:

 

使用内置的校验器

 我们导入使用的forms.xx字段类型

都在这下面:

进入邮件字段可知,它继承字符字段,默认的校验器是个列表,列表中是下面这个

 这个实际用的是邮件校验器。

那么我们也可以使用它们的校验器

 

 

is_valid的流程:

使用form组件实现注册方式

我们是访问到reg2函数等注册页面:当点击注册post请求的时候,用我们写的form实例化一个form对象。并将post数据封装到这个对象中。然后对这个对象使用is_valid()的方法。如果是有效的那么返回ture,并且生成对象.清洗了的数据。如果校验不通过,对象.清洗了的数据不会产生,校验通过就可以做插入数据库的操作(如果注册,插入数据库)。并返回一些内容。如果没有校验同那个

 

下面我们来看看对象.is_valid()执行做了什么。

返回了一个条件判断,下面先看is_bound

初始化基础form类的时候执行init。也就是只要数据或者文件传参了一个,那么is_bound结果就是true

我们从这里我们写的类又能点回到这里:

又回到这里了。

既然这里要传东西,那么我们看看我们传了什么,把data从post请求中获取的数据传参到里面了

由于data是第一个参数,所以data也可以不用写,位置传参。

data不是None了,那么is_bound就是true了

第一个form对象是个false,没有传递数据:

is_bound是true了,那么我们应该看后面的条件了。

 property,将这个方法变成属性了

因此errors虽然没加括号,但是它是属性,那么就会执行上面的方法

 如果私有为None,那么执行全清除方法,否则返回私有错误,下面先看看错误是啥

 还是基础form类的init方法中定义的

因为是None,所以我们需要执行全清除方法:

全清除中首先将刚才的self._errors赋值

 

错误字典又继承字典;

也就是首先定义了一个错误字典,现在是空的:

bound不用管。这就是我们之前说的只有执行is_valid()方法之后才会有清洗过的数据这个字典

也就是我们创建了两个字典,错误的(校验不通过的)放到错误字典里,正确的放到清洗了的数据字典里。然后执行三个私有方法,首先看第一个清洗字段的。

 

我们在页面点击注册,让程序执行到清除字段这里我们打印的内容(我们写的程序如果会运行到源码,当源码中执行结果不太清楚时,我们可以自己写个打印,查看自己写的代码中打印的结果)。这里self是我们的form对象

下面就是打印的数据,就是我们定义的那个类,生成form的post请求的数据内容。是个有序字典,键值对形式。它是按照我们定义的字段的顺序在字典里面存储的

for循环就是在拿键值对:

如果字段可以编辑的,那么获取它的初始值。获取当前字段的值

获取当前你页面输入框中输入的值;

填啥获取啥

 不是文件,所以字段清洗这些获取字段到的值(页面用户注册输入的内容)

点击查看清除方法:

可以看到clean()方法是Fiald类中的方法。很多个字段都继承的这个对象

看清除方法;

给了个参数又返回了

 那么value还是它本身,然后执行validate方法

当前在字段里面,self指的是字段对象,而不是类对象(自己创建的类)

这个方法是判断这个值在空的值并且在required里面,那么抛出异常。 这是执行它内部的方法,是否是必填的。

然后继续看清洗方法:

它执行校验器,self是字段对象,v就代表了字段的参数,v就是参数值

 

下面这个参数。v就是下面列表中的校验器

v执行我们自己写的那个校验器函数,value是我们获取到的用户输入的值

v加括号执行这个函数:如果通不过这个校验规则那么就报错

校验器执。try,如果不成功那么获取错误信息加到错误列表。如果错误列表有值,那么抛出错误。如果没有错误的话那么也没有给返回值

那么运行校验器执行完了。如果正常走完的话,value还是之前填写的值

如果运行校验器抛出异常了就不能返回value了

也就是form对象中的字段清洗做完了。只有都通过校验才能将值原路返回给form对象中的value

因此这一步做了如下两中校验:

 抛出异常并将当前字段的名字和异常错误提示做了如下函数操作

 

name就是它:

下面看看add_err做了啥,_errors就是那个错误字典,前面有写。将这个字段和错误列表以键值对形式写到错误字典;

 

再回到之前,这里校验通过之后将它添加到清洗了的数据字典里面。

self是form对象,name是from类中定义的字段。通过反射获取到这个方法  clean_字段名字

从我们的类中找下面这些方法

这样就用到了局部钩子,局部钩子就是对你的一个字段进行校验。下面clean_username就是对你的username字段进行校验。不会对你的其他字段影响。

钩子的含义就是我在这里写了,它就会执行,如果没有写那么它就不会执行。

源码中这里获取到就执行,获取不到直接就走了

如果我写了,那么get一下这个clean_字段名字的方法并执行,然后将执行返回值给value,然后重新将字段名和用户输入的值写到清洗了的数据字典中。如果执行错误那么剖出异常,添加到错误字典中

因此,我们要写的钩子是如下逻辑

因为我们将函数执行的返回值重新给value,然后添加到清洗了的数据字典中。所以我们必须返回当前字段的值,如果不返回那么value就是None,或者是有问题的值

看下:

 如果字段的名字在清洗的数据字典里面,那么把这个值删除掉

因为我1处添加了这个字段到清洗了的数据,在二处用我们写的钩子又校验一下并抛出了异常,那么我们应该将之前添加的数据删除掉,

所以add_error不只是将错误添加进去,如果后面自己写的钩子不通过而之前写入清洗了的数据字典里的数据删除掉

 

 这里能循环,对每个字段循环一次么?局部钩子也循环?

这样的话清除字段的方法已经执行完了。把内置校验器的规则,自定义规则,以及局部钩子都过了一遍,如果有错误那么error里面有错误的信息。如果是通过了校验,那么self.cleand_data里有我们的值

这一个做完了,该执行清除表单的方法了;

_clean_form方法又执行了一个try然后执行clean方法。

 clean方法里返回的是cleaned_data,全局钩子直接返回所有的信息

百度翻译:在field.clean()之后进行任何额外的窗体范围的清理在每一个字段上调用。此方法引发的任何validationError都将不与特定字段关联;它将具有特殊情况与名为“__all__”的字段关联。

比如注册中的密码,有了密码还有确认密码,需要把两次的值都拿出来之后再进行比较。上面是全局钩子

要想自己去响应的话需要自己去定义方法;

全局钩子:

如果类中写了自己的方法那么程序执行到clean方法的时候

执行的是自己的方法,且必须返回所有字段的值

如果不返回那么self.cleaned_data=None。如果有问题那么又add_errr()方法。

但是这里的给的值是个None,而之前给的第一个参数是字段名字,也就是如果全局出了问题的话,全局里面__all__里面去取

 

下面的执行完了,

那么这里全清除方法也就执行结束了,并且返回_errors,这是定义错误的那个字典

errors执行完了,如果not有值那么它是个False,前面true,后面false那么is_valid返回false;如果errors没有值,not没值那么is_valid返回的是true。所以is_valid做了很多校验

 

posted @ 2019-06-28 15:50  马昌伟  阅读(198)  评论(0)    收藏  举报
博主链接地址:https://www.cnblogs.com/machangwei-8/