array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 Django实战: 利用AJAX技术实现博文实时搜索 - 爱码网

学习Python Web和Django开发不能只学习Python。我们有时必需借助其它技术比如AJAX实现我们想要的功能。今天我们就要利用Django 2.0 + AJAX开发一个功能性页面: 我们一边输入关键词,网页一边会给你提示所找到的博文数量。


什么是AJAX技术?它的应用场景有哪些?

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。


Ajax常见应用场景包括:

  • 搜索提示: 在你输入关键词还未提交前,搜索框给你提示。

  • 用户名验证: 当你输入用户名时,页面提示你是否已注册。

  • 显示投票结果:用户投票后,不用加载页面即可显示投票结果。

  • 评论加载: 在你提交新的评论后,不用重新加载整个网页就会显示新提交的评论。


以上场景都是Django单靠自己无法实现的。注意Ajax应只用于与服务器少量数据交换,且存安全隐患,不宜广泛使用。


总体开发思路

我们创建一个叫blog的APP,并把它加入到INSTALLED_APP里去,然后在后台添加一些文章, 用于搜索(如下所示)。我们需要设计2个功能性页面: 一个展示博客文章清单,一个搜索页面。

Django实战: 利用AJAX技术实现博文实时搜索

下面我们来看下具体代码。


models.py

本案例中所用到的Article模型代码如下: 

from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.timezone import now


class Article(models.Model):

   STATUS_CHOICES = (
       ('d', '草稿'),
       
('p', '发表'),
   
)

   title = models.CharField('标题', max_length=200, unique=True)
   slug = models.SlugField('slug', max_length=60)
   body = models.TextField('正文')
   pub_date = models.DateTimeField('发布时间', default=now, null=True)
   create_date = models.DateTimeField('创建时间', auto_now_add=True)
   mod_date = models.DateTimeField('修改时间', auto_now=True)
   status = models.CharField('文章状态', max_length=1, choices=STATUS_CHOICES, default='p')
   views = models.PositiveIntegerField('浏览量', default=0)
   author = models.ForeignKey(User, verbose_name='作者', on_delete=models.CASCADE)


   def __str__(self):
       return self.title

   class Meta:
       ordering = ['-pub_date']
       verbose_name = "文章"
     


urls.py

前文提到过我们需要设计2个功能性页面: 一个展示博客文章清单,一个搜索。然而在urls.py里我们却设计了3个URL。这是因为我们还要设计一个URL与AJAX进行后台数据交换。这是用户看不见的,后面我们会用到这个URL。当ajax发送请求到/blog/ajax/search/时,Django就会调用ajax_search方法来处理。

from django.urls import path, re_path
from . import views

# namespace
app_name = 'blog'

urlpatterns = [

   # 搜索文章
   
re_path(r'^search/$', views.article_search, name='article_search'),

   
# 用于与ajax交互
   
re_path(r'^ajax/search/$', views.ajax_search, name='ajax_search'),

   
# 展示所有文章
   
path('', views.ArticleListView.as_view(), name='article_list'),

]


views.py

对应3个URL,我们需要在视图里编写3个处理方法,其中ajax_search用来给搜索页面返回Json数据(查询到的文章数量)。article_search方法用来返回搜索结果。我们为什么不用ajax_search返回搜索结果呢?因为查询到的数据集可能非常大,而ajax方法一般仅应用于与服务器的少量数据交换。


from django.views.generic import ListView
from .models import Article
from django.shortcuts import render
from .forms import SearchForm
from django.http import JsonResponse


# Create your views here.
class ArticleListView(ListView):
   queryset = Article.objects.filter(status='p').order_by('-pub_date')
   paginate_by = 6


def article_search(request):
   if request.method == 'GET':
       form = SearchForm(request.GET)
       if form.is_valid():
           keyword = form.cleaned_data.get("keyword")
           if keyword:
               article_list = Article.objects.filter(title__icontains=keyword)
               return render(request, 'blog/search.html', {'form': form, 'article_list': article_list})
   else:
       form = SearchForm()

   return render(request, 'blog/search.html', {'form': form, 'article_list': False, })


def ajax_search(request):
   if request.method == 'GET':
       keyword = request.GET.get('keyword', None)
       if keyword:
           count = Article.objects.filter(title__icontains=keyword).count()
           data = {'count': count, }
           return JsonResponse(data)

我们着重看下ajax_search是如何工作的。

  • 当搜索页面上ajax的通过GET发送请求时,服务器获取ajax发送过来的keyword。

  • 如果keyword不为空,服务器查询文章标题包含有keyword的文章数量。

  • 服务器将字典{‘count': count }转化为Json数据格式并返回给ajax所在页面。


模板blog/search.html

我们的模板blog/search.html代码如下:

{% block content %}
<h3>Django Ajax实时搜索文章</h3>

<form
method="get" action="">{% csrf_token %}
   {{ form }}
   <input type="submit" value="Search" />
</form>
{% endblock %}


<div id="result"></div>

<script
src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
   
$("#id_keyword").bind('input propertychange', function() {
     var keyword = $(this).val();

     $.ajax({
       url: '/blog/ajax/search/',
       data: {
         'keyword': keyword
       },
       type: 'GET',
       dataType: 'json',
       success: function (data) {
       $("#result").html("<p>正在实时查询..." + data.count + "条记录</p>")
       },

     });
   });
 </script>


{% if article_list %}
<p>共找到 {{ article_list | length }} 条记录。</p>
  <ul>
   
{% for article in article_list %}
  <li><a href="{% url 'blog:article_detail' article.id %}"> {{ article.title }}</a> {{ article.pub_date | date:"Y-m-j" }}</li>
   
{% endfor %}
  </ul>
{% endif %}

我们着重看下Ajax如何工作的。

  • 当搜索框#id_keyword有属性变化时,Ajax实时获取#id_keyword的值,并将其通过GET方法发送至url('/blog/ajax/search')。

  • Django视图里ajax_search方法处理ajax发来的请求,并返回json数据。

  • 如果服务器响应成功并成功发来json数据,将其显示在id=result的DIV里。


查看效果

下图是实时显示搜索结果数量的效果。随着关键词的增长,查询到的结果数量越来越少。

Django实战: 利用AJAX技术实现博文实时搜索

当你按Search提交后,article_search方法会返回查询结果。如下图所示:

Django实战: 利用AJAX技术实现博文实时搜索


Python Web开发与Django文章与教程每日更新。如果你喜欢我们的文章,欢迎关注我们的微信公众号。

Django实战: 利用AJAX技术实现博文实时搜索

相关文章: