Django进阶之Form
数据验证(非常强大)
Form操作动态select数据
通过下面例子进行理解:
在app目录下建立forms.py文件,写入如下代码:
这个时候页面的内容没有更新,只有重启程序之后才会更新
出现上述的原因是:
因为forms.py文件中的class UserInfoForm类中的user,pwd,usertype在类第一次加载的时候已经执行,所以这个时候user_type中的models.UserType.objects.values_list("id","name")操作已经从数据库取出数据存放在内存中,当再次刷新页面的时候,程序会直接从内存中获取对应的值,而不会再次进行数据库查询。
并且这个时候form还做一个一步操作,当我们在views函数里通过
obj = UserInfoForm() 创建form对象的时候,就会执行form中的__init__方法,__init__方法会把存在内存的字段封装到obj.fields中。所以就是每次创建form对象的时候都会去执行__init__方法,
所以为了解决修改数据库信息必须重启程序才能生效问题,
解决方法一,将views函数中的代码进行更改:
其实就是在创建对象之后再次进行数据库查询,但是这种方法并不完善,每次设计修改数据的都需要在创建form对象之后进行一次操作
解决方法二、重写form类的__init__构造方法
将form代码进行修改:
这里重写了__init__方法,并且上面user_type中的choices可以设置为[],因为下面的__init__方法中会再次查询数据库
Django自己的动态select数据
需要导入下面的模块
from django.forms import ModelChoiceField
在class UserInfoForm中添加
在ModelChoiceField的参数:
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示的内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选
Form的内置钩子
创建form对象的时候可以传递参数,例如
obj = UserInfoForm({"user":"zhaofan"})效果如下:
关于用户注册时的用法
在form类中写如下代码:
在views函数中写如下代码:
如果按照之前我们的习惯会判断if obj.is_valid()判断,这里的is_valid默认只是进行了正则的判断,如果需要判断用户名是否正确还需要到用obj.clean_data["user"],然后进行数据库操作
其实这样写是比较负载的,这里Django在is_valid这里给我们预留了钩子
我们查看源码,点击is_valid
然后点击errors继续查看源码
点击full_clean查看源码
点击_clean_fields查看源码
到这里的时候我们可以看出for循环先对各个字段的正则表达式进行验证,下面的hasattr(self, "clean_%s" %name)是进行判段是否有这个方法,这里就是留了钩子,这些方法用于我们自定义
我们在forms中的代码如下:
定义了clean_user方法以及clean_email方法,这里对用户进行了判断,如果用户存在了则提示用户密码已经存在,对于邮箱没有做操作
上面的这种是对单独的字段进行判断,还要一种情况是当用户是登录的时候,出现用户和密码都不正确,这个时候这个错误信息应该给整体,而不是某个单独字段,这里django同样给我们留了钩子,在full_clean方法中还有一个_clean_from
点击clean_form查看源码
点击clean继续查看源码,可以看出这里也是一个钩子
所以我们可以在forms文件中定义这个clean方法
同样的full_clean中还有一个_post_clean也是django预留的钩子,我们同样可以用于自定义
小结form数据验证顺序
1、先正则检查字段
2、然后执行_clean_%s 检查各个字段
3、执行_clean_form
4、最后执_post_clean
关于错误信息
当我们在在views函数中判断obj.is_valid(),如果返回true,则通过obj.cleaned_data可以获取正确的信息
如果错误可以通过obj.errors获取错误的信但是通过_clean_form验证整体的错误信息在obj.errors里面有一个“__all__”来存放整体错误信息
同样可以可以通过
from django.core.exceptions import NON_FIELD_ERRORS
这样就可以把__all__替换为NON_FIELD_ERRORS
关于序列化错误信息
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
之后我们可以规范代码,在app目录下存放一个views目录,在目录里定义不同的文件,用于不同的操作,例如我们可以把所有的用户操作都放在account.py文件中这样就不至于所有的操作都在一个views文件中
在app01/views/account.py文件中写入如下代码:
form中写入如下代码
.
前端中写如下代码:
这样我们在后台看结果可以看到type(obj.errors)的类型为:<class 'django.forms.utils.ErrorDict'>
我们导入这个模块,查看源码
可以看到这里有一个as_json的方法可以将结果转换为一个字符串
我们将前端页面的ajax部分代码进行更改:
这里我们查看结果可以看出,error部门拿到的还是字符串,所以需要再次JSON.parse
上面这种方式我们最终也能或得到对应的错误信息,但是相对来说并不是最好的
我们查看django.forms.utils.ErrorDict的ErrorDict源码是还有一个as_data方法,这个方法能让返回一个原生的字典
我们打印下面信息:
效果如下
我们查看from django.core.exceptions import ValidationError中ValidationError源码,可以看出里面封装了message,code,挺且可以通过messages获取所有的错误信息
obj.errors.as_data()虽然是个字典但是里面嵌套了ValidationError,所以不能直接json.dumps,所以我们需要定制化json.dumps
代码如下:
这样就不需要在前端页面中多次JSON.parse
关于返回为QuerySet类型的数据的序列化
第一种情况
当返回的为QuerySet类型的数据时
我们可以通过下面方式实现:
ret = models.tb.objects.values("id","name")
第二种情况
这样获得的QuerySet类型的数据中为字典
这里需要进行转换
ret = list(ret)
ret = json.dumps(ret)
以上是全部内容,只是善于分享,不足之处请包涵!爬虫基本的原理就是,获取源码,进而获取网页内容。一般来说,只要你给一个入口,通过分析,可以找到无限个其他相关的你需要的资源,进而进行爬取。
我也写了很多其他的非常简单的入门级的爬虫详细教程,关注后,点击我的头像,就可以查看到。
欢迎大家一起留言讨论和交流,谢谢!
本文暂时没有评论,来添加一个吧(●'◡'●)