django中的Form有个很重要的功能:验证用户输入

而验证用户输入也可以分为2种:

  (1)前端本身的验证,例如:字段是否可为空,手机号码格式是否正确等;

  (2)前端输入数据和后台数据库数据的验证,例如:注册的用户名是否已存在,邮箱是否注册过等;

本次主要针对第二种情况进行介绍,要实现前后端的数据验证我们可以使用ajax,也可以使用django form的clean_<fieldname>()函数。

下面先看clean_<fieldname>():

一个简单的添加用户的页面:

提交之后对用户进行后台验证,如果存在则会提示。

由上图我们可以的看到效果,具体实现代码:

html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>资源管理系统 - 人员管理</title>
<meta name="description" content="">
<meta name="author" content="templatemo">
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/css/templatemo-style.css" rel="stylesheet"> </head>
<body>
<!-- Left column -->
<div class="templatemo-flex-row">
<div class="templatemo-sidebar">
<div class="profile-photo-container">
<img src="/static/images/logo.png" alt="Profile Photo" class="img-responsive">
<div class="profile-photo-overlay"></div>
</div>
<header class="templatemo-site-header">
<div class="square"></div>
<h1>{{ user }}</h1>
</header> <nav class="templatemo-left-nav">
<ul>
<li><a href="/main/index/"><i class="fa fa-home fa-fw"></i>首页</a></li>
<li><a href="/main/managemachine/"><i class="fa fa-users fa-fw"></i>管理主机</a></li>
<li><a href="/main/manageuser/" class="active"><i class="fa fa-users fa-fw"></i>管理用户</a></li>
<li><a href="/main/managegroup/"><i class="fa fa-users fa-fw"></i>管理属组</a></li>
<li><a href="/main/manageidc/"><i class="fa fa-users fa-fw"></i>管理机房</a></li>
<li><a href="/main/managecity/"><i class="fa fa-users fa-fw"></i>管理城市</a></li>
<li><a href="/main/managerecord/"><i class="fa fa-users fa-fw"></i>巡检记录</a></li>
<li><a href="/main/maps/"><i class="fa fa-map-marker fa-fw"></i>地图</a></li>
<li><a href="/main/logout/"><i class="fa fa-eject fa-fw"></i>退出</a></li>
</ul>
</nav>
</div>
<!-- Main content -->
<div class="templatemo-content col-1 light-gray-bg"> <div class="templatemo-content-container">
<div class="templatemo-content-widget no-padding">
<div class="panel panel-default table-responsive">
<table class="table table-striped table-bordered templatemo-user-table">
<thead>
<tr>
<td>序号</td>
<td>用户名</td>
<td>部门</td>
<td>职位</td>
<td>电话</td>
<td>邮箱</td>
<td>编辑</td>
<td>删除</td>
</tr>
</thead>
<tbody>
{% for item in ret %}
<tr>
<td class="uid">{{ item.0 }}</td>
<td>{{ item.1 }}</td>
<td>{{ item.2 }}</td>
<td>{{ item.3 }}</td>
<td>{{ item.4 }}</td>
<td>{{ item.5 }}</td>
<td class="c1 templatemo-link"><a href="/main/updateuser/?g={{ item.0 }}">Edit</a></td>
<td class="c2 templatemo-link">Delete</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="templatemo-flex-row flex-content-row">
<div class="col-1">
<div class="panel panel-default margin-10">
<div class="panel-heading"><h2 class="text-uppercase">添加用户</h2></div>
<div class="panel-body">
<form action="/main/manageuser/" class="templatemo-login-form" method="POST">
<div class="form-group">
<label for="inputEmail">角色</label><span style="color: red"> *</span>
{{ data.role_choice }}
</div>
<div class="form-group">
<label for="inputEmail">用户名</label><span style="color: red"> *</span>
{{ data.username }}
{% if data.errors.username %}
<span style="color: red">{{ data.errors.username.0 }}</span>
{% endif %}
</div>
<div class="form-group">
<label for="inputEmail">密码</label><span style="color: red"> *</span>
{{ data.password }}
</div>
<div class="form-group">
<label for="inputEmail">确认密码</label><span style="color: red"> *</span>
{{ data.confirm_password }}
{% if data.errors.confirm_password %}
<span style="color: red">{{ data.errors.confirm_password.0 }}</span>
{% endif %}
</div>
<div class="form-group">
<label for="inputEmail">职位</label><span style="color: red"> *</span>
{{ data.job_choice }}
</div>
<div class="form-group">
<label for="inputEmail">邮箱</label>
{{ data.email }}
</div>
<div class="form-group">
<label for="inputEmail">电话</label>
{{ data.phone }}
{% if data.errors.phone %}
<span style="color: red">{{ data.errors.phone.0 }}</span>
{% endif %}
</div>
<div class="form-group">
<input type="submit" class="templatemo-blue-button" value="提交"/>
</div>
</form>
</div>
</div>
</div>
</div>
</div> <!-- Second row ends -->
<div class="pagination-wrap">
<ul class="pagination">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li class="active"><a href="#">3 <span class="sr-only">(current)</span></a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true"><i class="fa fa-play"></i></span>
</a>
</li>
</ul>
</div>
<footer class="text-right">
<p>Copyright © 2084 好医生运维部 | Designed by 无名小妖</p>
</footer>
</div>
</div> </body>
</html>

  

from:

class InsertForm(forms.Form):
"""添加用户验证"""
# django给标签加sytle,关键参数widget ,forms.TextInput 表示生成type="text"的input标签,改成Textarea则生成<textarea>标签
rolechoice = (
(1, '管理员'),
(2, '普通用户')
)
role_choice = forms.IntegerField(widget=forms.Select(choices=rolechoice, attrs={'class': 'form-control'}), )
username = forms.CharField(required=True, widget=forms.TextInput(attrs={'class': 'form-control'}))
password = forms.CharField(required=True, widget=forms.PasswordInput(attrs={'class': 'form-control'}),
min_length=6,
max_length=10,
error_messages={'required': '密码不能为空', 'min_length': '至少6位',
'max_length': '至多10位'})
confirm_password = forms.CharField(required=True,
widget=forms.PasswordInput(attrs={'class': 'form-control'}),
min_length=6,
max_length=10,
error_messages={'required': '密码不能为空', 'min_length': '至少6位',
'max_length': '至多10位'})
email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'form-control'}),)
# 自定制验证方法关键就是参数validators,和自己的函数关联起来
phone = forms.CharField(validators=[mobile_validate, ], widget=forms.TextInput(attrs={'class': 'form-control'}),)
# 获取数据库中的职位信息,显示在页面上
userjob = UserJob.objects.all().values_list('job_id', 'job_name')
# list indices must be integers or slices, not str 【此处不能用forms.CharField】
job_choice = forms.IntegerField(widget=forms.Select(choices=userjob, attrs={'class': 'form-control'})) def clean_username(self):
un = self.cleaned_data['username']
user = UserInfo.objects.filter(user_name=un)
if user:
raise ValidationError('用户名已存在!', code='valid')
return self.cleaned_data['username'] def clean_confirm_password(self):
p1 = self.cleaned_data['password']
p2 = self.cleaned_data['confirm_password']
if p1 != p2:
print(p2)
raise forms.ValidationError('两次密码不一致!')
return self.cleaned_data def __init__(self, *args, **kwargs):
"""
实时获取数据相应数据(否则数据库添加的新数据,在页面无法显示)
:param args:
:param kwargs:
"""
super(InsertForm, self).__init__(*args, **kwargs)
self.fields['job_choice'].widget.choices = UserJob.objects.all().values_list('job_id', 'job_name')

  

我们可以重点看 clean_username 函数,由于我们是要验证用户名(对应html 中name=username的input标签,此处我们是通过django from来生成的,可见html的代码),

所以函数名必须叫clean_username,函数内部对后台数据做了提取验证,并返回自定义的错误信息。

下面我们看ajax方式:

一个简单的添加城市的页面:

可以看到对数据的验证,代码就不详细贴了,主要看ajax部分:

<script src="/static/js/jquery-2.1.4.min.js"></script>
<script>
function DoSubmit() {
var input_dic = {};
$('input').each(function () {
var v = $(this).val();
var n = $(this).attr('name');
input_dic[n] = v;
});
$.ajax({
url:'/main/managecity/',
type:'POST',
data:input_dic,
dataType: 'json',
success: function (msg) {
if(msg.status){
location.href = '/main/managecity/'
}else{
$('#id_city_name').each(function () {
var tag = document.createElement('span');
tag.style = 'color: red';
tag.innerText = msg.message;
$(this).after(tag);
})
}
}
})
}

  

获取用户输入的数据,通过ajax传到views中对应的函数,通过函数进行后台数据验证。

views:

def managecity(req):
username = req.session.get('username')
ret = City.objects.all()
msg = {'status': False, 'message': None}
# 插入数据
if req.POST:
fm = CityForm(req.POST)
if fm.is_valid():
# 获取表单信息
city_name = fm.cleaned_data['city_name']
city = City.objects.filter(city_name=city_name).count()
if city:
msg['message'] = '数据已存在!'
else:
msg['status'] = True
City.objects.create(city_name=city_name)
return HttpResponse(json.dumps(msg)) # 将数据发送给ajax回调函数
else:
msg['message'] = '请填写此字段!'
return HttpResponse(json.dumps(msg)) # 将数据发送给ajax回调函数
else:
fm = CityForm() return render(req, 'manage-citys.html', {'user': username, 'data': ret, 'city': fm})

  

验证完之后,在通过ajax回调函数将提示信息显示在页面上显示。

总结:

这两种方式都实现了对表单数据的后台验证,

django form 的好处是只需要在定义一个函数即可,并且前端是看不到如何实现的,缺点是只能在django框架用;

而ajax在前端是可以通过查看页面代码看到的,好处是不管什么框架都可以用,而且ajax是“偷偷”发数据,页面不会刷新,但是django form会刷新页面;

有兴趣 可以看一下clean源码:

django表单的字段验证(clean_<fieldname>())和ajax的字段验证的更多相关文章

  1. django 表单验证和字段验证

    表单验证和字段验证 表单验证发生在数据验证之后.如果你需要自定义这个过程,有几个不同的地方可以修改,每个地方的目的不一样.表单处理过程中要运行三种类别的验证方法.它们通常在你调用表单的is_valid ...

  2. Django表单介绍

    HTML 表单 在HTML中,表单是<form>...</form> 之间元素的集合,它们允许访问者输入文本.选择选项.操作对象和控制等等,然后将信息发送回服务器. 某些表单的 ...

  3. django表单使用

    一.表单常用字段类型及参数 表单可以自动生成html代码,每一个字段默认有一个html显示样式,大多数默认为输入框. 字段相当于正则表达式的集合,能够对表单传入的数据进行校验,并且某一部分校验失败时会 ...

  4. python 全栈开发,Day111(客户管理之 编辑权限(二),Django表单集合Formset,ORM之limit_choices_to,构造家族结构)

    昨日内容回顾 1. 权限系统的流程? 2. 权限的表有几个? 3. 技术点 中间件 session orm - 去重 - 去空 inclusion_tag filter 有序字典 settings配置 ...

  5. python3之Django表单(一)

    1.HTML中的表单 在HTML种,表单是在<form>...</form>种的元素,它允许用户输入文本,选择选项,操作对象等,然后发送这些数据到服务器 表单元素允许用户在表单 ...

  6. django表单的api

    django表单的api,参考文档:https://yiyibooks.cn/xx/Django_1.11.6/ref/forms/api.html 绑定与未绑定形式: Form要么是绑定的,要么是未 ...

  7. Django表单API详解

    声明:以下的Form.表单等术语都指的的广义的Django表单. Form要么是绑定了数据的,要么是未绑定数据的. 如果是绑定的,那么它能够验证数据,并渲染表单及其数据,然后生成HTML表单.如果未绑 ...

  8. Django 表单处理流程

    Django 的表单处理:视图获取请求,执行所需的任何操作,包括从模型中读取数据,然后生成并返回HTML页面(从模板中),我们传递一个包含要显示的数据的上下文.使事情变得更复杂的是,服务器还需要能够处 ...

  9. 第四章:Django表单 - 2:Django表单API详解

    声明:以下的Form.表单等术语都指的的广义的Django表单. Form要么是绑定了数据的,要么是未绑定数据的. 如果是绑定的,那么它能够验证数据,并渲染表单及其数据,然后生成HTML表单.如果未绑 ...

  10. 第四章:Django表单 - 1:使用表单

    假设你想从表单接收用户名数据,一般情况下,你需要在HTML中手动编写一个如下的表单元素: <form action="/your-name/" method="po ...

随机推荐

  1. 【scala】IO

    1.读文件 可以使用Scala的Source类及其对象来读取文件. Source 类 需要导入 scala.io.Source 然后调用fromFile()方法来读取文件内容 import scala ...

  2. 【scala】类的定义和单例对象

    一.类的定义 Scala类的定义跟JAVA中类的定义基本是一样的. 示例 class ChecksumAccumulator{ var sum = 0;//Scala默认关键字为public priv ...

  3. 配置 Web 组件服务器 IIS 证书

    用 IIS 6 配置 Web 组件证书(对于 Windows Server 2003)     使用 IIS 管理器向 Web 组件服务器分配证书.对合并池配置中的 Standard Edition ...

  4. 用Spring和c3p0工具简单的实现增删改查

    1.导入Spring和c3p0的jar包 2.配置beans.xml文件 <?xml version="1.0" encoding="UTF-8"?> ...

  5. 地图之CoreLocation

    1. 在Info.plist文件中添加下面两句话 NSLocationAlwaysUsageDescription —> 确定定位吗?亲  (或者改参数类型为BOOL类型 值为Y) 请求的授权, ...

  6. 你不知道的sticky

    position:sticky,Chrome新版本已经做了支持.sticky的中文翻译是“粘性的”,position:sticky表现也符合这个粘性的表现.基本上,可以看出是position:rela ...

  7. ROS机器人星火计划公开课总结

    非常荣幸参加了两次星火计划公开课(上海站), 感谢NXROBO.EXBOT以及所有支持ROS机器人星火计划的小伙伴们. ----废话开始,与课程总结无关,可跳过---- 在国内20多年的求学生涯以及2 ...

  8. [分享]Google 全球 IP 地址库[Google Global Cache IPs]

    Google 全球 IP 地址库 IP 地址来源:http://www.kookle.co.nr,共计4351个. Bulgaria 93.123.23.1 93.123.23.2 93.123.23 ...

  9. iOS设置translucent 引发的坐标问题

    iOS  NavigationBar  + 导航栏 tablevie时候的布局情况,之前迷惑了我很久,怎么也没法理解透明度会影响布局. 接下来看一下以下三种情况的运行结果 1.全部系统默认情况下利用m ...

  10. FastAdmin 后台 UserRule 勾选不完整 Bug 修复

    FastAdmin 后台 UserRule 勾选不完整 Bug 修复 当用户权限的级选择时出现有部分没有选中. 修复来自在 qmit 1 public static function getTreeL ...