一 Form

在实际的生产环境中,登录和注册时用户提交的数据浏览器端都会使用JavaScript来进行验证(比如验证输入是否为空以及输入是否合法),但是浏览器可能会禁用JavaScirpt,同时也有人可能会搞注入攻击,这样浏览器端的验证就无法发挥作用(一般不会禁用),所以在实际项目中一般都会进行两层验证,即客户端(浏览器)的验证和服务器端的验证。Django中的Form表单功能之一就是用来在服务器端对用户提交的数据做验证;它的另外一个功能是生成HTML标签。

假如没有Django的Form表单,那么我们应该这么做

#/usr/bin/env python
#-*- coding:utf-8 -*- from django.shortcuts import render # Create your views here.
# 获取用户的相关信息
def user_list(request):
host = request.POST.get('host')
port = request.POST.get('port')
mail = request.POST.get('mail')
mobile = request.POST.get('mobile') # 在这里,存在两个问题
# 1、从用户提交的数据中获取具体字段的信息时,我们要不停得get相关信息,如果字段很多,显然过于繁琐
# 2、获取的数据,我们要自己进行合法性的验证或特定格式的验证,显然也很麻烦 return render(request,'user_list.html')

Django中Form的作用:(1)生成HTML标签;(2)用户提交数据验证

1 生成HTML标签

views.py文件

#!/usr/bin/env python
#-*- coding:utf-8 -*- from django import forms,render
# 用户信息Form表单类,继承自forms.Form
class UserInfo(forms.Form):
email = forms.EmailField(required=True) #required=True,表示内容不能为空
host = forms.CharField() #默认requried=False,表示内容可以为空
port = forms.CharField()
mobile = forms.CharField() # 定义函数,参数为request
def user_list(request):
obj = UserInfo() #创建对象obj
return render(request,'user_list.html',{'obj':obj})#把对象obj传给html

user_list.html文件

<form action="/user_list/" method="post">
<p>主机:{{ obj.host }}</p>
<p>端口:{{ obj.port }}</p>
<p>邮箱:{{ obj.email }}</p>
<p>手机:{{ obj.mobile }}</p>
<input type="submit" value="submit"/>
</form>

2 简单的Form表单验证

views.py文件

#!/usr/bin/env python
#-*- coding:utf-8 -*- from django import forms,render class UserInfo(forms.Form):
email = forms.EmailField(required=False) #required是否可以为空,如果为False说明可以为空
host = forms.CharField() #如果required不写,默认为Ture
port = forms.CharField()
mobile = forms.CharField() def user_list(request):
obj = UserInfo() #创建对象
if request.method == 'POST':
#获取用户输入,用户post的数据作为参数传递给UserInfo这个自定义的表单类,生成相应的对象后就可以做验证了
user_input_obj = UserInfo(request.POST)
#判断用户输入是否合法
if user_input_obj.is_valid():
#获取用户输入,这里获取的数据类型为字典
data = user_input_obj.clean()
# 如果不合法
else:
#捕捉错误信息
error_msg = user_input_obj.errors
print type(error_msg)
'''
<ul class="errorlist">
<li>mobile
<ul class="errorlist">
<li>This field is required.</li>
</ul>
</li>
<li>host
<ul class="errorlist">
<li>This field is required.</li>
</ul>
</li>
<li>port
<ul class="errorlist">
<li>This field is required.</li>
</ul>
</li>
</ul>
'''
#然后把错误信息返回
return render(request,'user_list.html',{'obj':obj,'errors':error_msg,})
return render(request,'user_list.html',{'obj':obj,})

user_list.html文件

<form action="/user_list/" method="post">
<p>主机:{{ obj.host }}<span>{{ errors.host }}</span></p>
<p>端口:{{ obj.port }}<span>{{ errors.port }}</span></p>
<p>邮箱:{{ obj.email }}<span>{{ errors.email }}</span></p>
<p>手机:{{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
<input type="submit" value="submit"/>
</form>

效果图:

3 自定义Form表单验证

app01下forms模块中的account.py文件

#!/usr/bin/env python
#-*- coding:utf-8 -*- from django import forms
from django.core.exceptions import ValidationError
import re #自定义手机号码验证方法
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') #正则匹配
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') #如果没有匹配到主动触发一个错误 class LoginForm(forms.Form):
user_type_choice = (
(1,'普通用户'),
(2,'超级用户'),
)
# 生成select标签,并且添加相应的属性
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'r'}))
# 参数required可以省略,默认required=True,表示不能为空
username = forms.CharField(required=True,error_messages={'required':u'用户名不能为空'})
password = forms.CharField(required=True,error_messages={'required':u'密码不能为空'})
mobile = forms.CharField(validators=[mobile_validate,], #应用自定义的验证方法
error_messages={'required':u'手机号码不能为空'},
# 生成提示信息,并且添加相应的属性
widget=forms.TextInput(attrs={'class':'r','placeholder':u'手机号码'})
) email = forms.EmailField(error_messages={'required':u'邮箱不能为空'},
# 生成提示信息,并且添加相应的属性,其中class=r是自定义的属性
widget=forms.TextInput(attrs={'class':'r','placeholder':u'邮箱'})
) # 新增一个
memo = forms.CharField(required=False,
widget=forms.Textarea(attrs={'class':'r','placeholder':'备注'})
)

app01下views模块中的account.py文件

#!/usr/bin/env python
#-*- coding:utf-8 -*- from django.shortcuts import render,HttpResponse
from app01.forms import account as AccountForm def login(request):
obj = AccountForm.LoginForm() # 生成Form对象
if request.method == 'POST':
user_input_obj = AccountForm.LoginForm(request.POST) # 把提交的数据封装到Form对象中
# 判断数据是否合法
if user_input_obj.is_valid():
# 获取提交的数据
data = user_input_obj.clean()
# 如果数据不合法
else:
error = user_input_obj.errors.as_data()
# 注意下面变量的类型
print type(error) # <type 'dict'> print error['username'] # [ValidationError([u'\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a'])]
print type(error['username']) # <type 'list'> print error['username'][0] #[u'\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a']
print type(error['username'][0]) #<class 'django.core.exceptions.ValidationError'> print error['username'][0][0] #用户名不能为空
print type(error['username'][0][0]) #<type 'unicode'> return render(request,'account/login.html',{'obj':obj,'error':error})
return render(request,'account/login.html',{'obj':obj})
#默认是as_ul(),即显示为ul的样式;如果写成as_data(),返回的是一个原生的字符串;as_json()与as_data()一样,
#也是返回的原生字符串
error_msg = user_input_obj.errors.as_data()

app01下的templatetags模块中的xx.py文件(因为模板语言不支持用索引的方式取值,所以我们通过自定义simp_tag来进行取值)

#!/usr/bin/env python
#-*- coding:utf-8 -*- from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError register = template.Library() @register.simple_tag
def error_msg(arg):
# 注意这里要做判断
if arg:
return arg[0][0]
# 这里的返回空字符串也是必须的,否则报错
return ''

templates/account目录下的login.html文件

{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/common.css"/>
</head>
<body>
<form action="/login/" method="post">
<p>
用户主机类型: {{ obj.user_type }}
</p> <p>
姓名: {{ obj.username }}
{#默认错误信息提示#}
{#<span> {{ error.username }}</span>#}
{#自定义错误信息提示#}
<span> {% error_msg error.username %}</span>
</p>
<p>
密码: {{ obj.password }}
{#<span> {{ error.password }}</span>#}
<span> {% error_msg error.password %}</span>
</p>
<p>
手机号码: {{ obj.mobile }}
{#<span> {{ error.mobile }}</span>#}
<span> {% error_msg error.mobile %}</span>
</p>
<p>
邮箱: {{ obj.email }}
{#<span> {{ error.email }}</span>#}
<span> {% error_msg error.email %}</span>
</p>
<p>
备注: {{ obj.memo }}
</p> <input type="submit" value="提交"/> </form> </body>
</html>

二 Ajax

Django中怎么把前端数据在不刷新前端页面的前提下提交到后台,这里涉及到Django中Ajax提交数据到后台的问题。主要包括:(1)利用Ajax把前端简单数据(单条)提交到后台;(2)利用Ajax把前端复杂数据(多条)提交到后台。

1 提交单条数据

html页面,注意其中的注释

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax提交数据</title>
</head>
<body>
<form action="/user_list/" method="post">
{# 提交数据button #}
<input type="button" onclick="Ajaxsubmit();" value="Ajax提交"/>
<table>
<thead>
<tr>
<th>主机名</th>
<th>端口</th>
</tr>
</thead>
<tbody>
<tr>
<td>1.1.1.1</td>
<td>80000</td>
</tr>
<tr>
<td>1.1.1.1</td>
<td>80000</td>
</tr>
</tbody>
</table>
</form>
<script type="text/javascript" src="/static/jquery-2.2.1.min.js"></script>
<script type="text/javascript">
function Ajaxsubmit(){
{# 这里应该从表格中获取数据,为了省事这里直接指定了数据 #}
var host = '1.1.1.1';
var port = '8000'; $.ajax({
{# 提交到后台的url #}
url:"/ajax_data/",
{# 提交到后台的方式 #}
type:'POST',
{# 要提交的数据,简单数据直接以字典的形式提交 #}
data:{h:host,p:port},
{# 提交成功后要执行的函数,函数内容此处省略 #}
success:function(arg){ }
})
}
</script>
</body>
</html>

views.py文件

def ajax_data(request):
# 打印前端POST提交的数据
print request.POST
return HttpResponse('ok')

2 提交多条数据

在上述的基础上修改jQuery代码

<script>
function AjaxsubmitSet(){
var user_arr = [
{'username':'alex','age':18},
{'username':'eric','age':28},
{'username':'rain','age':38}, ];
{# Ajax提交 #}
$.ajax({
url:"/ajax_data_set/",
type:'POST',
data:{data:user_arr},
success:function(arg){ }
})
}
</script>

提交后打印的数据如下所示:

<QueryDict: {u'data[1][username]': [u'alex'], u'data[0][username]': [u'eric'], u'data[0][age]': [u''], 
u'data[1][age]': [u''], u'data[2][username]': [u'rain'], u'data[2][age]': [u'']}>

这明显不符合格式要求,需要我们进一步进行处理,继续修改Ajax提交代码如下:

<script>
function AjaxsubmitSet(){
var user_arr = [
{'username':'alex','age':18},
{'username':'eric','age':28},
{'username':'rain','age':38},
]; $.ajax({
{# Ajax提交url #}
url:"/ajax_data_set/",
{# Ajax提交方式 #}
type:'POST',
{# Ajax以原生的数据格式进行提交 #}
tradition:true,
{# Ajax提交只能处理字符粗,不能处理字典,这里把字典转换成字符串形式 #}
data:{data:Json.stringify(user_arr)},
success:function(arg){ }
})
}
</script>

3 进一步改进规范的写法

views.py文件的修改

import json
# 后台向前端返回数据
def ajax_data(request):
# 设置初始的返回值
ret = {'status':True,'error':''}
# 捕捉错误
try:
print request.POST
except Exception,e:
#异常时,ret[status] = False
ret['status'] = False
# 注意这里的str,这里是把e封装成字符串形式
ret['error'] = str(e)
# 由于ret是字典形式,但是HttpResponse只能返回字符串,所以这里把ret通过json.dumps()转换成字符串形式
return HttpResponse(json.dumps(ret))

jQuery部分的修改

<script>
function Ajaxsubmit(){
var user_arr = [
{'username':'alex','age':18},
{'username':'eric','age':28},
{'username':'rain','age':38}, ];
{# Ajax提交数据 #}
$.ajax({
{# Ajax提交url #}
url:"/ajax_data/",
{# Ajax以POST方式提交 #}
type:'POST',
{# Ajax以原生形式提交数据 #}
tradition: true,
{# Ajax只能提交字符串数据,这里把字典转换为字符串 #}
data:{data:JSON.stringify(user_arr)},
{# Ajax提交执行成功后的执行代码,arg是后台返回的数据,切记 #}
success:function(arg){
//这里把后台返回的字符串arg转换为字典形式
var callback_dict = $.parseJSON(arg);
//这里只做简单的判断,判断后台返回的是否为空
if(callback_dict){
//不为空,则执行成功了
alert('提交成功')
}else{
//否则,执行失败了
alert(callback_dict.error)
}
}
})
}
</script>

参考资料:

http://www.cnblogs.com/wupeiqi/articles/5246483.html

http://www.cnblogs.com/luotianshuai/p/5278175.html

Django基础——Form&Ajax篇的更多相关文章

  1. Django基础之Ajax

    知识预览 Ajax前戏:json Ajax简介 Jquery实现的ajax JS实现的ajax Ajax前戏:json 什么是json? 定义: JSON(JavaScript Object Nota ...

  2. django基础 -- 7.Ajax

    一.ajax 的特点 1.异步交互:客户端发出一个请求后,需要等待服务器响应结束后, 才能发出第二个请求 2.局部刷新:给用户的感受是在不知不觉中完成请求和响应过程. 二.ajax 模板示例 ($.a ...

  3. django基础之Ajax、分页、cookie与session

    目录: Ajax之json Ajax简介 jquery实现的ajax js实现的ajax django分页器 COOKIE与SESSION 一.Ajax之json 1.什么是json? 定义: JSO ...

  4. Django基础第三篇

    一.ORM操作 1.常用字段和参数 Autofied 自增的整形字段,必填参数primary_key=True,  则成为数据库的主键,如无该字段,django自动创建 IntegerField 一个 ...

  5. Django如何与ajax通信

    示例一 文件结构 假设你已经创建好了一个Django项目和一个App,部分结构如下: mysite myapp |___views.py |___models.py |___forms.py |___ ...

  6. {Django基础七之Ajax} 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解)

    Django基础七之Ajax 本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 一 Ajax简介 ...

  7. 01: Django基础篇

    目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...

  8. day 72 Django基础七之Ajax

    Django基础七之Ajax   本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 六 同源策略与 ...

  9. day 60 Django基础七之Ajax

      Django基础七之Ajax   本节目录 一 Ajax简介 二 Ajax使用 三 Ajax请求设置csrf_token 四 关于json 五 补充一个SweetAlert插件(了解) 六 同源策 ...

随机推荐

  1. rhel7防止开机破密码

    在/etc/grub.d/00_header文件结尾加入  cat <<EOF set  superusers="qin"#用户名称可以更加自身编辑 password ...

  2. Codeforces Round #325 垫底纪念

    A. Alena's Schedule 间隔0长度为1被记录  1被记录  其余不记录 #include <iostream> #include <cstring> #incl ...

  3. CMS为什么采用“标记-清除”算法

    分代式GC里,年老代常用mark-sweep:或者是mark-sweep/mark-compact的混合方式,一般情况下用mark-sweep,统计估算碎片量达到一定程度时用mark-compact. ...

  4. C# random生成随机数全部一样

    最近做排序测试  使用random生成随机数全部一样 估计是因为random采用的随机种子为时间戳 而一个循化执行消耗的时间没有到时间戳的最小单位 故没有变化 Thread.Sleep(10); 使用 ...

  5. linux桌面环境gnome,kde,xfce,lxde 使用比较(转)

    Linus Torvalds大神前几日在 Google+上表示,GNOME 3"无可容忍的凌乱",改投Xfce桌面环境.下面就GNOME, KDE, XFCE和 LXDE略作比较. ...

  6. 11 个 Linux 上最佳的图形化 Git 客户端

    Git是软件开发和若干其他版本控制任务免费和开源的分布式版本控制系统.它被设计用来以应付一切从小到非常大的项目,基于速度,效率和数据完整性. Linux用户主要通过命令行管理Git,不过,一些图形用户 ...

  7. PHP中的 extends与implements 区别 [转]

    extends 是继承某个类 继承之后可以使用父类的方法 也可以重写父类的方法 implements 是实现多个接口 接口的方法一般为空的 必须重写才能使用 extends是继承父类,只要那个类不是声 ...

  8. 《UML大战需求分析》阅读笔记2

    在第三章往后的章节里面,作者着重描述了uml各个图的具体用法,首先则是类图. 类图则表示程序中所出现的用到的类,用方框来表示,方框中分为三行,第一行是类的名字,第二行是类的成员变量(属性),第三行是成 ...

  9. 网页中插入swf动画(embed)

    网页中插入swf动画(embed:[ɪm'bed]) 例题: <embed src="swf.sef" width="200" height=" ...

  10. 用dom4j解析xml 报java.lang.NoClassDefFoundError:org/jaxen/JaxenException

    转自:http://www.myexception.cn/java%20exception/95.html 源码如下: import java.io.File; import java.util.Li ...