基于How To Tango With Django 1.9的重新实践(19)——Ajax

来源:互联网 发布:莫比乌斯环戒指知乎 编辑:程序博客网 时间:2024/06/02 09:40

19.1 AJAX基本功能
为了使我们无缝的和Rango进行交互,让我们用AJAX加入一些特性,例如:

  • 增加”Like Button”让注册用户可以”like”一个特殊的目录
  • 增加一个行内的目录建议 - 这样当用户键入的时候就能很快的找到目录
  • 增加”Add Button”使用户快速的方便的为目录添加页面

创建rango-ajax.js文件并放入到js目录.然后在你的基础模板里:

<script src ="{% static "js/jquery-3.2.0.min.js" %}"> </script><script src ="{% static "js/rango-jquery.js" %}"> </script><script src ="{% static "js/rango-ajax.js" %}"></script>

19.2 增加”Like Button”

对于注册用户可以标记”like”一个目录是很友好的.接下来,我们将让用户”like”目录,但是我们将不会跟踪用户已经”like”的目录,我们相信用户不会重复点击喜欢按钮.

19.2.1 工作流程

为了让用户”like”特定的目录需要以下步骤:

在cateegory.html模板:

  • 增加”like”按钮并且使用id=”like”.
    • 增加一个模板标签来展示喜欢的数量:{{% category.likes %}}
    • 添加一个div并使用id=”like_count”,例如: <div id="like_count">{{ category.likes }} </div>
    • 设置完后模板会获取喜欢并且展示喜欢的目录
    • 注意,因为category()视图会传递一个目录对象的引用,我们可以使用{{ category.likes }}来获取用户喜欢数
  • 创建like_category视图,它将会检测请求并取出category_id参数,并且增加喜欢目录的数目.
    • 不要往家增加url映射;例如把like_category视图映射到rango/like_category/.GET请求将会是rango/like_category/?category_id=XXX样式.
    • 和以往返回HTML页面不同,这个视图将返回新的喜欢目录总数.
  • 现在在rango-ajax.js文件中加入JQuery代码来发送AJAXGET请求.
    • 如果请求成功, 修改#like_count元素并隐藏喜欢按钮.

19.2.2 修改目录模板

我们需要添加id=”like”的”Like”按钮,并且创建一个<div>来展示喜欢数量{{% category.likes %}}.

<strong id="like_count">{{ category.likes }}</strong> people like this category{% if user.is_authenticated %}        <button id="likes" data-catid="{{category.id}}" class="btn btn-primary" type="button">        <span class="glyphicon glyphicon-thumbs-up"></span>        Like        </button>{% endif %}

19.2.3 创建喜欢目录视图

在rango/views.py里创建like_category视图,它会检测请求并抽取出category_id然后增加喜欢目录的数量

from django.contrib.auth.decorators import login_required@login_requireddef like_category(request):    cat_id = None    if request.method == 'GET':        cat_id = request.GET['category_id']    likes = 0    if cat_id:        cat = Category.objects.get(id=int(cat_id))        if cat:            likes = cat.likes + 1            cat.likes =  likes            cat.save()    return HttpResponse(likes)

这里只有注册用户才有权限标记喜欢的目录.这是视图假设通过GET方式传递进一个category_id变量,这样我们可以知道要更改哪个目录.在这个视图里,如果我们需要的话可以跟踪和记录特定用户喜欢的目录 - 但是在这里我们为了保持AJAX简单就不这样做了.

不要忘记在rango/urls.py里增加URL映射.修改urlpatterns如下:

url(r'^like_category/$', views.like_category, name='like_category'),

19.2.4 设置AJAX请求

现在需要在rango-ajax.js里添加一些JQuery代码来完成AJAXGET请求.增加代码如下:

$('#likes').click(function(){    var catid;    catid = $(this).attr("data-catid");    $.get('/rango/like_category/', {category_id: catid}, function(data){               $('#like_count').html(data);               $('#likes').hide();    });});

这段JQuery/Javascript代码将会处理id为#likes的元素,例如按钮.当点击过后,它将会从按钮元素里抽取出category的id,并把category_id写入一个AJAXGET请求中,这个请求的地址是/rango/like_category/.如果请求成功的话,这个id为like_count的HTML元素将会更新为返回的内容,而id为likes的按钮将会被隐藏.

这背后运行的机理有些复杂.基本上,当一个按钮被点击后就会生成一个AJAX请求,它将会映射到相应的url,传递给like_category视图,最后视图将会更改目录并返回新的喜欢数目.当AJAX请求得到响应它就会修改部分页面,例如文本和按钮.#like按钮将会被隐藏.

19.3 增加行内目录提示
如果我们提供给用户快速寻找目录的方法那就再好不过了,而不是让用户浏览尝尝的列表.我们可以创建一个提示组建使用户输入一个字母或单词的一部分,然后会返回一个提示目录列表,这样用户就可以选择它们了.随着用户的输入服务器返回的目录将会更加接近用户所需要的.

19.3.1 工作流程

你需要以下步骤.

  • 创建一个带参函数get_category_list(max_results=0,starts_with=''),如果max_result=0的话它会返回所有以starts_with开头的目录,否则的话它会返回最多max_results个目录.
    • 这个函数将会返回一个目录对象的列表,连同它们已经编码过后的url属性.
  • 创建一个叫做suggest_category的视图,它将会检测请求并抽取目录查询语句.
    • 假设GET请求已经生成并尝试得到查询属性.
    • 如果查询语句非空,询问目录模型获取获取8个最前面的以查询字符串为首的目录.
    • 这个目录对象列表将会通过模板整合进HTML的一部分.
  • 我们不用再新建一个suggestions.html模板了,我们可以重用cats.html.它可以展示同样类型的数据.(目录)
  • 让客户端请求这个数据,你需要创建一个URL映射:让我们命名为category_suggest好了映射视图和模板后,你需要修改base.html模板并添加一些javascript代码以便展示用户输入的目录.
  • 在base.html模板里修改侧边栏,添加进一个id=”cats”的<div>以便呈现目录.JQuery/AJAX将会修改这个元素.
    • 在这个<div>上面添加一个输入框使用户可以输入目录的字母,例如:<input class="input-medium search-query" type="text" name="suggestion" value="" id="suggestion" />
  • 当这些元素都添加修改完毕,你需要添加一些JQuery代码来修改用户输入所呈现的目录列表.
    • 在input里关联一个id为”suggestion”的按键事件
    • $(‘#suggestion’).keyup(function(){ … })
    • 当按键结束抬起时调用一个ajax来请求更新目录列表
    • 然后使用JQuery.get()函数,例如$(this).get( … )
    • 如果调用成功,用返回的数据替换id=”cats”的<div>.
    • 这里你可以使用JQuery的.html()函数,例如$(‘#cats’).html( data )

19.3.2 参数化获取目录列表函数

在这个函数的帮助下,我们使用一个过滤器来查找以提供的字符串开头的目录.我们将使用istartwith来进行过滤,它可以确保输入的大小写无关.如果想使用大小写相关那就久使用startswith来替代.

def get_category_list(max_results=0, starts_with=''):        cat_list = []        if starts_with:                cat_list = Category.objects.filter(name__istartswith=starts_with)        if max_results > 0:                if len(cat_list) > max_results:                        cat_list = cat_list[:max_results]        return cat_list

19.3.4 映射视图到URL

在rango/urls.py的urlpatterns元组增加以下:

url(r'^suggest/$', views.suggest_category, name='suggest_category'),

19.3.5 修改基础模板
在基础模板的侧边栏加入<div>如下:

ul class="nav nav-list">        <li class="nav-header">Find a Category</li>        <form>        <label></label>        <li><input  class="search-query span10" type="text" name="suggestion" value="" id="suggestion" /></li>        </form></ul><div id="cats"></div>

这里我们加入了一个id=”suggestion”的输入框和一个id=”cats”的div(这个div用来展示返回结果).我们这里不需要加入按钮,因为我们添加了一个按键抬起的事件,触发它可以传送提示请求.

19.3.6 增加AJAX请求提示

在js/rango-ajax.js增加如下:

$('#suggestion').keyup(function(){        var query;        query = $(this).val();        $.get('/rango/suggest_category/', {suggestion: query}, function(data){         $('#cats').html(data);        });});

这里我们绑定了一个id=”suggestion”的输入框来捕捉按键抬起事件.当它获取输入框的内容后会把让放入query变量.然后会调用一个AJAXGET请求,这个请求里包含query参数.如果请求成功,这个id=”cats”的HTML元素(div)会更新目录列表.

19.4 练习

为了让注册用户快速简单的添加一个页面到目录里,在每个搜索结果旁边添加”Add”按钮.

  • 修改category.html模板:
    • 在每个搜索结果后面加入一个小按钮(如果用户已经验证),同时加入标题和url信息,以便JQuery能够抽取出来.
    • 在目录的每个页面都用id=”page”的<div>包含,这样当页面增加的时候会更新. 如果你喜欢的话移除增加按钮的链接.
    • 增加一个auto_add_page视图,它会接收GET请求的参数(title,utl,catid)并且添加到目录.
  • 映射视图到url(r'^auto_add_page/$', views.auto_add_page,name='auto_add_page')
  • 使用JQuery绑定按钮事件 - 当添加过后隐藏按钮.同时也修改目录页的那些页面.

19.4.1 提示

HTML模板代码:

{% if user.is_authenticated %}        <button data-catid="{{category.id}}" data-title="{{ result.title }}" data-url="{{ result.link }}" class="rango-add btn btn-mini btn-info" type="button">Add</button>{% endif %}

JQuery代码:

注意这里我们需要绑定所有rango-add类按钮的事件.

视图代码:

@login_requireddef auto_add_page(request):    cat_id = None    url = None    title = None    context_dict = {}    if request.method == 'GET':        cat_id = request.GET['category_id']        url = request.GET['url']        title = request.GET['title']        if cat_id:            category = Category.objects.get(id=int(cat_id))            p = Page.objects.get_or_create(category=category, title=title, url=url)            pages = Page.objects.filter(category=category).order_by('-views')            # Adds our results list to the template context under name pages.            context_dict['pages'] = pages    return render(request, 'rango/page_list.html', context_dict)

JQuery code:

$('.rango-add').click(function(){    var catid = $(this).attr("data-catid");        var url = $(this).attr("data-url");        var title = $(this).attr("data-title");        var me = $(this)        $.get('/rango/auto_add_page/', {category_id: catid, url: url, title: title}, function(data){                        $('#pages').html(data);                        me.hide();                        });                                });

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

3 0