一 Form

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

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

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

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

1 生成HTML标签

views.py文件

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

user_list.html文件

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

2 简单的Form表单验证

views.py文件

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3.  
  4. from django import forms,render
  5.  
  6. class UserInfo(forms.Form):
  7. email = forms.EmailField(required=False) #required是否可以为空,如果为False说明可以为空
  8. host = forms.CharField() #如果required不写,默认为Ture
  9. port = forms.CharField()
  10. mobile = forms.CharField()
  11.  
  12. def user_list(request):
  13. obj = UserInfo() #创建对象
  14. if request.method == 'POST':
  15. #获取用户输入,用户post的数据作为参数传递给UserInfo这个自定义的表单类,生成相应的对象后就可以做验证了
  16. user_input_obj = UserInfo(request.POST)
  17. #判断用户输入是否合法
  18. if user_input_obj.is_valid():
  19. #获取用户输入,这里获取的数据类型为字典
  20. data = user_input_obj.clean()
  21. # 如果不合法
  22. else:
  23. #捕捉错误信息
  24. error_msg = user_input_obj.errors
  25. print type(error_msg)
  26. '''
  27. <ul class="errorlist">
  28. <li>mobile
  29. <ul class="errorlist">
  30. <li>This field is required.</li>
  31. </ul>
  32. </li>
  33. <li>host
  34. <ul class="errorlist">
  35. <li>This field is required.</li>
  36. </ul>
  37. </li>
  38. <li>port
  39. <ul class="errorlist">
  40. <li>This field is required.</li>
  41. </ul>
  42. </li>
  43. </ul>
  44. '''
  45. #然后把错误信息返回
  46. return render(request,'user_list.html',{'obj':obj,'errors':error_msg,})
  47. return render(request,'user_list.html',{'obj':obj,})

user_list.html文件

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

效果图:

3 自定义Form表单验证

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

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

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

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

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

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

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

  1. {% load xx %}
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>Title</title>
  7. <link rel="stylesheet" href="/static/css/common.css"/>
  8. </head>
  9. <body>
  10. <form action="/login/" method="post">
  11. <p>
  12. 用户主机类型: {{ obj.user_type }}
  13. </p>
  14.  
  15. <p>
  16. 姓名: {{ obj.username }}
  17. {#默认错误信息提示#}
  18. {#<span> {{ error.username }}</span>#}
  19. {#自定义错误信息提示#}
  20. <span> {% error_msg error.username %}</span>
  21. </p>
  22. <p>
  23. 密码: {{ obj.password }}
  24. {#<span> {{ error.password }}</span>#}
  25. <span> {% error_msg error.password %}</span>
  26. </p>
  27. <p>
  28. 手机号码: {{ obj.mobile }}
  29. {#<span> {{ error.mobile }}</span>#}
  30. <span> {% error_msg error.mobile %}</span>
  31. </p>
  32. <p>
  33. 邮箱: {{ obj.email }}
  34. {#<span> {{ error.email }}</span>#}
  35. <span> {% error_msg error.email %}</span>
  36. </p>
  37. <p>
  38. 备注: {{ obj.memo }}
  39. </p>
  40.  
  41. <input type="submit" value="提交"/>
  42.  
  43. </form>
  44.  
  45. </body>
  46. </html>

二 Ajax

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

1 提交单条数据

html页面,注意其中的注释

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Ajax提交数据</title>
  6. </head>
  7. <body>
  8. <form action="/user_list/" method="post">
  9. {# 提交数据button #}
  10. <input type="button" onclick="Ajaxsubmit();" value="Ajax提交"/>
  11. <table>
  12. <thead>
  13. <tr>
  14. <th>主机名</th>
  15. <th>端口</th>
  16. </tr>
  17. </thead>
  18. <tbody>
  19. <tr>
  20. <td>1.1.1.1</td>
  21. <td>80000</td>
  22. </tr>
  23. <tr>
  24. <td>1.1.1.1</td>
  25. <td>80000</td>
  26. </tr>
  27. </tbody>
  28. </table>
  29. </form>
  30. <script type="text/javascript" src="/static/jquery-2.2.1.min.js"></script>
  31. <script type="text/javascript">
  32. function Ajaxsubmit(){
  33. {# 这里应该从表格中获取数据,为了省事这里直接指定了数据 #}
  34. var host = '1.1.1.1';
  35. var port = '8000';
  36.  
  37. $.ajax({
  38. {# 提交到后台的url #}
  39. url:"/ajax_data/",
  40. {# 提交到后台的方式 #}
  41. type:'POST',
  42. {# 要提交的数据,简单数据直接以字典的形式提交 #}
  43. data:{h:host,p:port},
  44. {# 提交成功后要执行的函数,函数内容此处省略 #}
  45. success:function(arg){
  46.  
  47. }
  48. })
  49. }
  50. </script>
  51. </body>
  52. </html>

views.py文件

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

2 提交多条数据

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

  1. <script>
  2. function AjaxsubmitSet(){
  3. var user_arr = [
  4. {'username':'alex','age':18},
  5. {'username':'eric','age':28},
  6. {'username':'rain','age':38},
  7.  
  8. ];
  9. {# Ajax提交 #}
  10. $.ajax({
  11. url:"/ajax_data_set/",
  12. type:'POST',
  13. data:{data:user_arr},
  14. success:function(arg){
  15.  
  16. }
  17. })
  18. }
  19. </script>

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

  1. <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提交代码如下:

  1. <script>
  2. function AjaxsubmitSet(){
  3. var user_arr = [
  4. {'username':'alex','age':18},
  5. {'username':'eric','age':28},
  6. {'username':'rain','age':38},
  7. ];
  8.  
  9. $.ajax({
  10. {# Ajax提交url #}
  11. url:"/ajax_data_set/",
  12. {# Ajax提交方式 #}
  13. type:'POST',
  14. {# Ajax以原生的数据格式进行提交 #}
  15. tradition:true,
  16. {# Ajax提交只能处理字符粗,不能处理字典,这里把字典转换成字符串形式 #}
  17. data:{data:Json.stringify(user_arr)},
  18. success:function(arg){
  19.  
  20. }
  21. })
  22. }
  23. </script>

3 进一步改进规范的写法

views.py文件的修改

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

jQuery部分的修改

  1. <script>
  2. function Ajaxsubmit(){
  3. var user_arr = [
  4. {'username':'alex','age':18},
  5. {'username':'eric','age':28},
  6. {'username':'rain','age':38},
  7.  
  8. ];
  9. {# Ajax提交数据 #}
  10. $.ajax({
  11. {# Ajax提交url #}
  12. url:"/ajax_data/",
  13. {# AjaxPOST方式提交 #}
  14. type:'POST',
  15. {# Ajax以原生形式提交数据 #}
  16. tradition: true,
  17. {# Ajax只能提交字符串数据,这里把字典转换为字符串 #}
  18. data:{data:JSON.stringify(user_arr)},
  19. {# Ajax提交执行成功后的执行代码,arg是后台返回的数据,切记 #}
  20. success:function(arg){
  21. //这里把后台返回的字符串arg转换为字典形式
  22. var callback_dict = $.parseJSON(arg);
  23. //这里只做简单的判断,判断后台返回的是否为空
  24. if(callback_dict){
  25. //不为空,则执行成功了
  26. alert('提交成功')
  27. }else{
  28. //否则,执行失败了
  29. alert(callback_dict.error)
  30. }
  31. }
  32. })
  33. }
  34. </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. ListView和ScrollView冲突

    当ListView放在ScrollView中的时候,无论你设置高度为 match_parent(填充父窗体)和wrap_content(包裹内容)都只显示一行,这是你把ListView放在Linear ...

  2. MYSQL存储过程:批量更新数据

    地区等级的信息储存在jsjh_district表. 要更新jsjh_goods_district表的district_level地区信息 DELIMITER $$ DROP PROCEDURE IF ...

  3. 【实(dou)力(bi)首(mai)发(meng)】第四次CCF软件能力认证题解

    这次的题总体上相对前三次偏简单.由于实力有限,就分析前四题.     试题编号:    201503-1 试题名称:    图像旋转 时间限制:    5.0s 内存限制:    256.0MB 问题 ...

  4. iOS获取通讯录 电话号码与姓名

    // 还是导入 #import <AddressBook/AddressBook.h> - (void)fetchAddressBookBeforeIOS9{ ABAddressBookR ...

  5. checkbox和radio使用

    jQuery获取Radio选择的Value值: jQuery   C#   VB   C++   Java jQuery设置Radio的Value值: 语法解释: 1. $("input[n ...

  6. 手写DataSet,DataTable

    一:DataSet DataSet ds = new DataSet();//创建DataSet DataTable dt = new DataTable();//创建一个DataTalbe dt.C ...

  7. 玩转React样式

    很久很久以前,就有人用CSS来时给HTML内容添加样式.CSS可以最大限度的分离样式和内容,选择器也可以很方便的给某些元素添加样式.你根本找不到任何不用CSS的理由. 但是在React这里就是另外一回 ...

  8. 数据库知识整理<八>

    联接: 8.1理解简单的单联接: 基本上联接的结果是每个集合的笛卡尔积.例如:两个集合{a,b,c}和{a,b}的笛卡尔积是如下的成对集合:{(a,a),(a,b),(b,a),(b,b),(c,a) ...

  9. sublime Text3 插件编写教程_第一课

    今天给大家分享一下编写一个Sublime Text3 插件的流程以及使用插件解决的一个实际问题. 一.开发插件的前提条件 开发sublime插件用到的是Python语言,因此必须懂Python语言的基 ...

  10. C#函数式编程之递归调用

    关于递归相信大家已经熟悉的不能再熟悉了,所以笔者在这里就不多费口舌,不懂的读者们可以在博客园中找到很多与之相关的博客.下面我们直接切入正题,开始介绍尾递归. 尾递归 普通递归和尾递归如果仅仅只是从代码 ...