python测试开发django-114.ModelForm中局部钩子(clean_)和全局钩子校验

前言

在实际开发中,不仅仅是对输入框字符的格式校验,比如注册功能,注册账号还得校验数据库是否已经有账号被注册过了。
有些场景不仅仅是对单个输入框的字符校验,比如修改密码的时候,会涉及2个输入框的数据格式校验,像这些复杂的场景校验需用到校验钩子来实现。
校验form表单数据合法性,is_valid()方法调用顺序:

  • 1.字段规则校验,字符长度,是否必填等基本校验

  • 2.validators校验(RegexValidator校验器或自定义校验函数)

  • 3.局部钩子(类中定义的以clean_字段名命名的函数,校验正常必须返回该字段的值self.cleaned_data.get('name’))

  • 4.全局钩子(类中定义的函数名clean,校验正常必须返回该对象的校验结果值return self.cleaned_data)

  • 5.每一步通过校验单结果都以字典形式保存在类对象的cleaned_data属性中

ModelForm模型表单

局部钩子命名规则为clean字段名称,如:cleancity,clean_years。
super() 重写`__init`,可以批量更新class属性。

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class SubmitPageForm(forms.ModelForm):

class Meta:
model = Submit
# fields = "__all__" #全部字段
fields = ["city", "years", "details"]
widgets = {
"city": widgets.TextInput(attrs={
"placeholder": "输入城市:北京/上海/深圳"
}),
"years": widgets.TextInput(attrs={
"placeholder": "输入年限"}),
"details": widgets.TextInput(attrs={
"placeholder": "输入详情"}),

}
labels = {
"city": "城 市",
"years": "年 限",
"details": "详 情",
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 批量更新class属性
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})

def clean_city(self):
"""局部钩子判断城市必须是北京/上海/深圳其中一个"""
city_val = self.cleaned_data.get('city', '')
if city_val in ["北京", "上海", "深圳"]:
return city_val
else:
raise forms.ValidationError('城市只能选:北京/上海/深圳')

定义视图

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class SubmitView(View):

def get(self, request):
form_obj = SubmitPageForm
return render(request, "submit.html", locals())

def post(self, request):
form_obj = SubmitPageForm(request.POST)
if form_obj.is_valid():
# data = form_obj.cleaned_data()
form_obj.save()
msg = "保存成功"
return HttpResponseRedirect('/total')

else:
# 全局钩子自定义错误提示获取
# print(form_obj.errors.get('__all__'))
# error_msg = form_obj.errors.get('__all__')
return render(request, "submit.html", locals())

模板内容

模板内容如下

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>提交页面</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>

<div class="container">

<form role="form" action="" method="POST" id="detail-form" >
{% csrf_token %}
{% for field in form_obj %}
<div class="form-group">
{{ field.label_tag }}
{{ field }}
<div style="color: red"> {{ field.errors }} </div>

</div>

{% endfor %}
<p>
<input type="submit" value="提交" >
</p>
</form>
</div>
</body>
</html>

页面效果

输入不合法的内容,会显示field.errors内容

全局钩子

针对单个字段校验可以用局部钩子实现,如果我们要校验多个字段,比如校验注册的时候输入2次密码一致,可以用全局钩子实现。
定义全局钩子使用clean方法

# 作者-上海悠悠 QQ交流群:717225969
# blog地址 https://www.cnblogs.com/yoyoketang/

class SubmitPageForm(forms.ModelForm):

class Meta:
model = Salary
fields = "__all__" #全部字段
# 省略中间代码。。。。。# 全局钩子
def clean(self):
"""在通过基础验证的干净数据中get获取字段"""
pwd1 = self.cleaned_data.get('password')
pwd2 = self.cleaned_data.get('password2')
if pwd1 and pwd2: # 这里判断2个字段都是校验通过
if pwd1 == pwd2:
# 数据没问题,那么原封不动返回即可
return self.cleaned_data
else:
# 错误信息储存到 errors {'__all__':[e,]}
raise ValidationError('两次密码输入不同')
else:
return self.cleaned_data

前端可以通过fomr_obj.errors.__all__获取到内置校验器的全部错误信息

(0)

相关推荐

  • drf—— 序列化组件

    ----->序列化器-Serializer 一.序列化组件介绍 #作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 -Book模型--序列化器-- ...

  • 类的进阶

    面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个"函数"供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的 ...

  • DjangoRestFramework使用

    目录: 1.1 DjangoRestFramework基本使用 1.2 drf认证&权限 模块 1.3 djangorestframework 序列化 1.4 djangorestframew ...

  • 11 Serializer组件

    知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 为什么要使用序列化组件? 视图中查询到的对象和queryset类型不 ...

  • 面向对象的详细解读

      面向对象的详细解读 一.基本概念 1. 面向过程 (1) 概念:以过程为中心的编程思想,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了. (2 ...

  • Django-Vue搭建个人博客:Markdown正文

    原创 杜赛 杜赛说编程 博客文章需要排版,否则难以凸显标题.正文.注释等内容之间的区别.作为博客写手来说,比较流行且好用的排版是采用 Markdown 语法. 严格来说, Markdown 是一种排版 ...

  • python测试开发django-99.views视图中 locals() 函数使用

    前言 locals() 函数是python内置函数,会以字典类型返回当前位置的全部局部变量. Python locals() 函数 locals() 函数语法:locals() 参数无,返回字典类型的 ...

  • python测试开发django-106.form表单中局部钩子(clean_)和全局钩子校验

    前言 在实际开发中,不仅仅是对输入框字符的格式校验,比如注册功能,注册账号还得校验数据库是否已经有账号被注册过了. 有些场景不仅仅是对单个输入框的字符校验,比如修改密码的时候,会涉及2个输入框的数据格 ...

  • python测试开发django -140.Bootstrap 缩略图

    前言 网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 class .thumbnail 的& ...

  • python测试开发django -143.Bootstrap 表单控件校验状态

    前言 Bootstrap 对表单控件的校验状态,如 error.warning 和 success 状态,都定义了样式.使用时,添加 .has-warning..has-error 或 .has-su ...

  • python测试开发django -142.Bootstrap 表单(form)

    前言 HTML 表单用于收集不同类型的用户输入.boostrap中表单有几种样式 基本垂直表单 内联表单 form-inline 水平排列表单 form-horizontal 基本表单实例 单独的表单 ...

  • python测试开发django -141.Bootstrap 面板(Panels)

    # 前言 面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 元素添加 class .panel 和 class .panel-default 即可 基础面板 不带标题的基本面 ...

  • python测试开发django -144.Ace Editor 在线编辑python代码

    前言 网页上想在线编辑代码,可以使用Ace Editor 在线编辑实现.比如我们想实现一个功能,在网页版上写python代码,能有python的语法自动补齐功能. Ace Editor 在线编辑 AC ...

  • python测试开发django-6.模板中include使用

    前言 当我们打开一个网站的时候,在打开不同的页面时候,会发现每个页面的顶部.底部内容都差不多,这样就可以把这些公共的部分,单独抽出来. 类似于python里面的函数,把公共部分写成函数,然后调用就行了 ...

  • python测试开发django-10.django连接mysql

    前言 Django 对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite.Oracle.本篇以mysql为例简单介绍django连接mysql进行数据操作 Django连 ...