1. 程式人生 > >Django實戰: 利用AJAX技術實現博文實時搜尋

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個功能性頁面: 一個展示部落格文章清單,一個搜尋頁面。

下面我們來看下具體程式碼。

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裡。

檢視效果

下圖是實時顯示搜尋結果數量的效果。隨著關鍵詞的增長,查詢到的結果數量越來越少。

當你按Search提交後,article_search方法會返回查詢結果。如下圖所示:

Python Web開發與Django文章與教程每日更新。如果你喜歡我們的文章,歡迎關注我們的微信公眾號。