编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Python学习之路Django进阶之Form,各种疑难杂症详细讲解(附步骤)

wxchong 2024-07-22 22:42:50 开源技术 12 ℃ 0 评论

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)


以上是全部内容,只是善于分享,不足之处请包涵!爬虫基本的原理就是,获取源码,进而获取网页内容。一般来说,只要你给一个入口,通过分析,可以找到无限个其他相关的你需要的资源,进而进行爬取。


我也写了很多其他的非常简单的入门级的爬虫详细教程,关注后,点击我的头像,就可以查看到。

欢迎大家一起留言讨论和交流,谢谢!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表