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文章與教程每日更新。如果你喜歡我們的文章,歡迎關注我們的微信公眾號。