最近想在使用django的基础上通过jquery实现页面局部刷新的功能,研究了两天,终于是解决了这个问题,下面把方法步骤记录下来,以备以后重用。
在项目中通过两种形式实现了ajax:
第一种方法:web前端发送数据给服务器,服务器接收到数据后在服务端生成需要刷新的局部页面,然后把这个页面返回给web前端,前端直接使用这个页面来替换原页面;
第二种方法:和第一种方法的区别是服务器只生成需要的数据,将数据返回给web前端,前端通过jquery的dom方法来修改原页面的dom。
第一种方法的演示:
(1)前端的javascript代码:
1 $(document).ready(function() { 2 $('#weaponSearchForm').submit(function(event) { 3 event.preventDefault(); //阻止表单提交的默认方法 4 var formValues = $('form').serialize(); //将表单的元素序列化为字符串 5 $.ajax({ 6 dataType: "json", 7 data: formValues, 8 type: $(this).attr('method'), 9 url: $(this).attr('action'), 10 success: function(responseData) { //responseData是从服务器返回的数据 11 $('#table_container').html(responseData.content_html); 12 } 13 }); 14 //return false; 15 }); 16 });
(2) django的urls.py文件添加一项
url(r'^main/info/$', Info.as_view(), name='info'),
(3)django的views.py中的视图
1 class Info(View): 2 template_name = "info.html" 3 4 @csrf_exempt 5 @method_decorator(login_required(login_url='/login/')) 6 def dispatch(self, *args, **kwargs): 7 return super(Info,self).dispatch(*args, **kwargs) 8 9 #用于呈现演示的这个页面 10 def get(self, request, *args, **kwargs): 11 12 …… 13 …… 14 15 return render(request,self.template_name,{}) 16 17 18 def post(self, request, *args, **kwargs): 19 if request.is_ajax(): 20 #这里搞了好久,用了request.raw_post_data和request.body都不行 21 #raw_post_data已经被弃用,request.body得到的是一个字符串,如果 22 #数据里包含中文,则中文会被显示为一些无法解析的字符。 23 #django对解析发送来的数据的方法进行了封装,不管客户端 24 #发送来的是普通数据还是json数据,都用request.POST或request.GET 25 #进行解析 26 b_id = request.POST['bID'] 27 c_id = request.POST['cID'] 28 29 t = get_template('search.html') 30 #strength_list是你需要生成的数据 31 content_html = t.render(Context({ 32 'user': request.user, 33 'strength_list': strength_list})) 34 payload = { 35 'content_html': content_html, 36 'success': True} 37 return HttpResponse(json.dumps(payload), 38 mimetype="application/json") 39 else: 40 return HttpResponse('error')
上述代码需要注意的一点是,如果你使用的是post方法,django默认会进行csrf的检查,所以你需要在你的视图函数上加上@csrf_exempt这个装饰器。
第二种方法的演示:
为了实现选择框的级联动作,也就是第二个选择框中的内容会根据第一个选择框中选中的项进行自动更新。数据库中的结构就不说了,看下前端的jquery代码:
1 $(document).ready(function() { 2 $('#bID').change(function(event) { 3 var selectValue = $(this).serialize(); 4 $.ajax({ 5 dataType: "json", 6 type: "POST", 7 data: selectValue, 8 url: "/info/selectbat/", //最后一个斜杠千万不能少了,否则django的地址映射会不成功 9 success: function(responseData) { 10 $('#cID').removeAttr('disabled'); 11 $('#cID').empty(); 12 var html = '<option value=""></option>'; 13 $.each(responseData, function(entryIndex, entry) { 14 html += '<option value="' + entry[0] + '">'; 15 html += entry[1]; 16 html += '</option>'; 17 }) 18 $('#cID').html(html); 19 } 20 }); 21 }); 22 });
选择框的级联功能同样是在方法一介绍的那个页面中实现的,我这里用得方法也是post,当然,仍然可以在方法一中的那个类视图中实现,但是,为了让各个模块的功能更单一,我就把级联这个功能放在另一个类视图中实现,一个视图函数不一定非要呈现页面,它也可以返回数据,只要数据是HttpResponse对象即可。url.py文件中添加一行,让jquery中的设置的url和urls.py文件中的项匹配就行,看下视图中的代码:
1 class SelectView(View): 2 3 @csrf_exempt 4 @method_decorator(login_required(login_url='/login')) 5 def dispatch(self, *args, **kwargs): 6 return super(SelectView,self).dispatch(*args, **kwargs) 7 8 def get(self,request,*args,**kwargs): 9 pass 10 11 def post(self,request,*args,**kwargs): 12 if request.is_ajax(): 13 b_id = request.POST['bID'] #得到post中的数据 14 15 comp_list = 你通过数据库查询到的数据 16 payload = [] 17 for entry in comp_list: 18 payload.append([entry.id,entry.name]) 19 20 return HttpResponse(json.dumps(payload), 21 mimetype='application/json') 22 else: 23 return HttpResponse("error")
代码看起来不复杂,但是在真正实现的过程中走了不少弯路,问题还是出在对django不是很熟。有时候在问题长时间无法解决时需要我们停下来想一想问题的症结在哪里,然后再对症下药。
下一步还需要通过ajax实现文件的上传功能,以后再添加吧。