当前位置: 首页 > news >正文

[pthon2.7+django1.2+sae]博客评论的异步提交

在开发博客系统或者是电商系统,总之,凡是带有回复、评论、回帖之类针对一个内容进行回复的功能的时候,现在几乎全部都是采用ajax异步提交,并且同步在正确的位置显示提交结果,而不是在提交之后重新刷新整个页面来显示提交之后的内容。

ajax由于google的使用,被广为推广。它在客户端使用javascript语言编写,使用XMLHttpRequest对象,实现和服务的数据交互,详细信息参看:AJAX - XMLHttpRequest 对象。

ajax提交或者获取数据,常用数据形式包括:

  • 普通文本,自己定义规则,自己解析,无成熟类库,需要自己编写。
  • xml文本,使用xml解析器解析,有成熟类库。
  • json文本,流行的数据形式,以体积小、灵活而著称,有成熟类库。

ajax有几个好处:

  • 防止页面刷新,因为提交的只是一部分内容,页面大部分内容没有发生改变,如果还是刷新进而重新获取全部的话,对于服务器和客户端都是一种负担。而且页面刷新还会产生其他问题,诸如重复提交之类的。
  • 减轻服务器负担,可以为更多人提供服务。

也有一些缺点:

  • 给编程和调试带来一些小麻烦,不够使用习惯了,还是有一些方法和窍门的。
  • 由于是ajax,所以页面地址没有变化,所以如果想分享地址的话,难以实现。需要做额外的工作,例如把地址打印出来,让用户复制分享。
  • 用户不容易知道自己的提交正在进行,因为页面没有刷新,用户可能会重新点击提交按钮。这也可以解决,提交过程给出明显提示,然后灰掉提交按钮,或者做一些防止重复提交的工作。

 

今天的例子是博客评论的异步提交,环境是python2.7+django1.2+SAE。

下面是后台的处理代码,view中的代码

 

 
 
  1.                       
  2. @csrf_exempt                  
  3. def comment_new(request,blog_id): 
  4.     blog=get_object_or_404(Blog,pk=blog_id) 
  5.      
  6.     #str(request.raw_post_data) 
  7.     if request.method=="POST" and request.is_ajax(): 
  8.         title=request.POST['comment_title'
  9.         name=request.POST['comment_author_name'
  10.         email=request.POST['comment_author_email'
  11.         url=request.POST['comment_author_url'
  12.         content=request.POST['comment_content'
  13.         comment=Comment(title=title,author_name=name,author_email=email,author_url=url,content=content); 
  14.         comment.blog=blog 
  15.         comment=comment.save() 
  16.  
  17.         _dict={} 
  18.         _dict["title"]=title 
  19.         _dict["author_name"]=name 
  20.         _dict["author_email"]=email 
  21.         _dict["author_url"]=url 
  22.         _dict["content"]=content 
  23.           _dict["created_at"]=unicode(datetime.datetime.now()) 
  24.      
  25.      
  26.     return HttpResponse(simplejson.JSONEncoder().encode(str(_dict))) 
  27.  
  28.  
  29. def obj2dict(obj): 
  30.     """ 
  31.     summary: 
  32.         将object转换成dict类型     
  33.     """ 
  34.     memberlist = [m for m in dir(obj)] 
  35.     _dict = {} 
  36.     for m in memberlist: 
  37.         if m[0] != "_" and not callable(m): 
  38.             _dict[m] = getattr(obj,m) 
  39.  
  40.     return _dict 

 

下面是前段页面的代码

 

 
 
  1. <script type="text/javascript" src="/site_static/js/tiny_mce_jquery/tiny_mce.js"></script> 
  2. <script type="text/javascript" src="/site_static/js/textareas_simple.js"></script> 
  3.  
  4. {% if comments %} 
  5. <p> 
  6. <h2>Comments:</h2> 
  7. <div id="blog_comments"> 
  8. {% for comment in comments %} 
  9. <p> 
  10. <a href="{{ comment.author_url }}">{{ comment.author_name }}</a>&nbsp;&nbsp;Said at {{ comment.created_at }} 
  11. </p> 
  12. <p> 
  13. <h3>Title:</h3> 
  14. {{ comment.title }} 
  15. </p> 
  16. <p> 
  17.     <h3>Content:</h3> 
  18.     {% autoescape off %} 
  19.     {{ comment.content }} 
  20.     {% endautoescape %} 
  21.  
  22. </p> 
  23. <hr> 
  24. {% endfor %} 
  25.  
  26. </div> 
  27.  
  28. </p> 
  29. {% else %} 
  30. <h2>you are the first comment man, please!</h2> 
  31. {% endif %} 
  32. <p> 
  33. <h2>New Comment:</h2> 
  34. <script type="text/javascript"> 
  35.     $(document).ready(function(){ 
  36.         $("#comment_form").submit(function(e){ 
  37.                      
  38.             var data=$('#comment_form').serialize(); 
  39.              
  40.             $.ajax({ 
  41.                 url:"/blog/{{ blog.id }}/comment/new/", 
  42.                 type:"POST", 
  43.                 contentType:"application/json; charset=utf-8", 
  44.                 dataType:"json", 
  45.                 data:data, 
  46.                 success:function(data, textStatus, jqXHR){ 
  47.                     //alert(typeof(data)); 
  48.                     datadata=data.replace(/'/gi,"\""); 
  49.                     datadata=data.replace(/u"/gi,"\""); 
  50.                     //alert(data); 
  51.                     var obj=$.parseJSON(data); 
  52.                     //alert(obj.content); 
  53.                     $("#blog_comments").append("<p><a href=\""+obj.author_url+"\">"+obj.author_name+"</a>&nbsp;&nbsp;Said at "+obj.created_at+"</p><p>"+obj.title+"</p><p>"+obj.content+"</p><hr>"); 
  54.                      
  55.                     $("#comment_form")[0].reset(); 
  56.                 }, 
  57.                 error:function(jqXHR, textStatus, errorThrown){ 
  58.                     alert(textStatus); 
  59.                     alert(errorThrown); 
  60.                 } 
  61.             });      
  62.              
  63.             return false; 
  64.  
  65.         }); 
  66.     }); 
  67.      
  68. </script> 
  69. <form method="post" action="" id="comment_form"> 
  70.  
  71.     {% csrf_token %} 
  72.      
  73.     {% comment %} 
  74.     {% for field in comment_form %} 
  75.     <p> 
  76.         {{ field.errors }} 
  77.         {{ field.label_tag }}:{{ field }} 
  78.     </p> 
  79.     {% endfor %} 
  80.          
  81.     {% endcomment %} 
  82.  
  83.     <p> 
  84.     <label for="comment_title">{{ comment_form.title.label }}</label>
  85.     <input type="text" id="comment_title" name="comment_title"  placeholder="Title"/> 
  86.     {{ comment_form.title.help_text }} 
  87.     </p> 
  88.      
  89.     <p> 
  90.     <label for="comment_author_name">{{ comment_form.author_name.label }}</label>
  91.     <input type="text" id="comment_author_name" name="comment_author_name" placeholder="author name"/> 
  92.     {{ comment_form.author_name.help_text }} 
  93.     </p> 
  94.      
  95.     <p> 
  96.     <label for="comment_author_email">{{ comment_form.author_email.label }}</label>
  97.     <input type="text" id="comment_author_email" name="comment_author_email"  placeholder="author email"/> 
  98.     {{ comment_form.author_email.help_text }} 
  99.     </p> 
  100.      
  101.     <p> 
  102.     <label for="comment_author_url">{{ comment_form.author_url.label }}</label>
  103.     <input type="text" id="comment_author_url" name="comment_author_url"  placeholder="author url"/> 
  104.     {{ comment_form.author_url.help_text }} 
  105.     </p> 
  106.      
  107.     <p> 
  108.     <label for="comment_content">{{ comment_form.content.label }}</label>
  109.     <textarea rows="10" cols="50" placeholder="content" id="comment_content" name="comment_content"></textarea> 
  110.      
  111.     {{ comment_form.content.help_text }} 
  112.     </p> 
  113.      
  114.  
  115.  
  116.  
  117.      
  118.      
  119.     <input type="submit" value="Save" /> 
  120. </form> 
  121.  
  122. </p> 

在客户端用到了三个类库,分别是jquery-1.7.1.min.js,jquery.json-2.3.min.js和jquery.placeholder.min.js。

jquery是一个javascript类库,封装了javascript的很多操作,使用方便。

jquery.json是jquery的一个扩展,用来处理json文本和object之间的转换。

jquery.placeholder是jquery的一个扩展,用来实现在输入框没有内容的时候,添加一些提示信息。在输入框没有内容的时候,显示一些内容,提示你应该输入什么,输入的格式是什么。【placeholder是html5支持的一个属性,专门用来做提示的。】

 

 
 
  1. datadata=data.replace(/'/gi,"\"");  
  2. datadata=data.replace(/u"/gi,"\"");  

前段页面的上面这两句需要大家注意,第一句用正则表达式替换【单引号】为【双引号】,第二句替换【u+双引号】为【双引号】。这都是为了后面使用

$.parseJSON(data); 

做准备的。因为python后台返回的json字符串,也就是data的值是下面的格式

 

 
 
  1. {'title':u'blog1','author':u'andyshi'

字符串中有单引号和u,这都需要替换,jquery解析的json必须是标准格式的,就是双引号,而且不能包含其他内容,所以我进行了替换,然后才可以使用jquery.json进行解析。

u是因为python后台返回的是unicode字符串的缘故。应该有办法解决,待我再研究一下,稍后补充上来。

 

补充:

之前ajax返回的数据还需要处理单引号和字母u的问题,现在修正一下。

首先将前端的ajax代码变更为

 

 
 
  1. $.ajax({ 
  2.                 url:"/blog/{{ blog.id }}/comment/new/"
  3.                 type:"POST"
  4.                 contentType:"application/json; charset=utf-8"
  5.                  
  6.                 data:data, 
  7.                 success:function(data, textStatus, jqXHR){ 
  8.  
  9.                     var obj=$.parseJSON(data); 
  10.                      
  11.                     $("#blog_comments").append("<p><a href=\""+obj.author_url+"\">"+obj.author_name+"</a>&nbsp;&nbsp;Said at "+obj.created_at+"</p><p>"+obj.title+"</p><p>"+obj.content+"</p><hr>"); 
  12.                     $("#comment_form")[0].reset(); 
  13.                 }, 
  14.                 error:function(jqXHR, textStatus, errorThrown){ 
  15.                     alert(textStatus); 
  16.                     alert(errorThrown); 
  17.                 } 
  18.             });  

很明显,就是去掉了ajax参数dataType,返回的结果变成在服务端组织好的json字符串,然后用jquery.json解析成对象。顺便里面的两次替换就可以去掉了。

python后台的view代码变更为

 

 
 
  1. @csrf_exempt                  
  2. #@csrf_protect 
  3. def comment_new(request,blog_id): 
  4.     blog=get_object_or_404(Blog,pk=blog_id) 
  5.      
  6.     #str(request.raw_post_data) 
  7.     if request.method=="POST" and request.is_ajax(): 
  8.         title=request.POST['comment_title'
  9.         name=request.POST['comment_author_name'
  10.         email=request.POST['comment_author_email'
  11.         url=request.POST['comment_author_url'
  12.         content=request.POST['comment_content'
  13.         comment=Comment(title=title,author_name=name,author_email=email,author_url=url,content=content); 
  14.         comment.blog=blog 
  15.         comment=comment.save() 
  16.          
  17.     #return string 
  18.     return HttpResponse("{\"title\":\"%s\",\"author_name\":\"%s\",\"author_email\":\"%s\",\"author_url\":\"%s\",\"content\":\"%s\",\"created_at\":\"%s\"}"  
  19.         % (title,name,email,url,content,unicode(datetime.datetime.now()))) 

直接返回我们自己构造的字符串,构造的时候就使用双引号拼接。这样就给前台省去了正则替换的操作。

 




本文转自 virusswb 51CTO博客,原文链接:http://blog.51cto.com/virusswb/802039,如需转载请自行联系原作者

相关文章:

  • angular2 学习一 注解/Annotation
  • Android输入事件详解
  • HTML基础第十一讲---背景标志
  • Linux使用mount挂载samba共享
  • 由socket的accept说开去
  • CentOS 6.7安装Sqoop 1.4.6
  • SELinux上课内容
  • 浅谈Android编码规范及命名规范
  • 实现一些常用字符串处理函数
  • [摘录]第11章 造就优势谈判的驱动力
  • java调用斑马GK888t打印机(ZPL指令)
  • 允许chrome 浏览器运行 flash player
  • 注解的使用
  • hadoop各个组件功能
  • 命令行创建虚拟机,无桌面运行virtualbox
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • ➹使用webpack配置多页面应用(MPA)
  • angular2 简述
  • Git同步原始仓库到Fork仓库中
  • Java 内存分配及垃圾回收机制初探
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • JS字符串转数字方法总结
  • mongodb--安装和初步使用教程
  • oldjun 检测网站的经验
  • yii2中session跨域名的问题
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 将回调地狱按在地上摩擦的Promise
  • 理清楚Vue的结构
  • 前端面试题总结
  • 算法之不定期更新(一)(2018-04-12)
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​VRRP 虚拟路由冗余协议(华为)
  • #100天计划# 2013年9月29日
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (rabbitmq的高级特性)消息可靠性
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (第一天)包装对象、作用域、创建对象
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET 回调、接口回调、 委托
  • .net反编译的九款神器
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET上SQLite的连接
  • [Android] Android ActivityManager
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [APIO2015]巴厘岛的雕塑
  • [C++]模板与STL简介
  • [C++]拼图游戏
  • [GN] 后端接口已经写好 初次布局前端需要的操作(例)
  • [iHooya]2023年1月30日作业解析
  • [LeetBook]【学习日记】数组内乘积