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源码: