做者:HelloGitHub-追夢人物html
文中所涉及的示例代碼,已同步更新到 HelloGitHub-Team 倉庫python
搜索是一個複雜的功能,但對於一些簡單的搜索任務,咱們可使用 Django Model 層提供的一些內置方法來完成。如今咱們來爲咱們的博客提供一個簡單的搜索功能。ios
博客文章一般包含標題和正文兩個部分。當用戶輸入某個關鍵詞進行搜索後,咱們但願爲用戶顯示標題和正文中含有被搜索關鍵詞的所有文章。整個搜索的過程以下:git
整個過程就是這樣,下面來看看 Django 如何用實現這些過程。github
先來回顧一下咱們的 Django 博客的 Post(文章)模型:數據庫
blog/models.py
class Post(models.Model):
# 標題
title = models.CharField("標題", max_length=70)
# 正文
body = models.TextField("正文")
# 其餘屬性...
def __str__(self):
return self.title
複製代碼
先看到第 1 步,用戶在搜索框輸入搜索關鍵詞,所以咱們要在博客上爲用戶提供一個搜索表單,HTML 表單代碼大概像這樣:django
templates/base.html
<form role="search" method="get" id="searchform" action="{% url 'blog:search' %}">
<input type="search" name="q" placeholder="搜索" required>
<button type="submit"><span class="ion-ios-search-strong"></span></button>
</form>
複製代碼
特別注意這裏 <input type="search" name="q" placeholder="搜索" required>
中的 name 屬性,當用戶在這個 input 中輸入搜索內容並提交表單後,鍵入的數據會以鍵值對的形式提交服務器,這個鍵的名字就是經過 name 屬性指定的。這樣服務器就能夠根據 name 的值來取得用戶輸入的內容。編程
用戶輸入了搜索關鍵詞並點擊了搜索按鈕後,數據就被髮送給了 Django 後臺服務器。表單的 action
屬性的值爲 {% url 'blog:search' %}(雖然咱們尚未寫這個視圖函數),代表用戶提交的結果將被髮送給 blog 應用下 search 視圖函數對應的 URL。服務器
搜索的功能將由 search 視圖函數提供,代碼寫在 blog/views.py 裏:app
blog/views.py
from django.contrib import messages
def search(request):
q = request.GET.get('q')
if not q:
error_msg = "請輸入搜索關鍵詞"
messages.add_message(request, messages.ERROR, error_msg, extra_tags='danger')
return redirect('blog:index')
post_list = Post.objects.filter(Q(title__icontains=q) | Q(body__icontains=q))
return render(request, 'blog/index.html', {'post_list': post_list})
複製代碼
首先咱們使用 request.GET.get('q')
獲取到用戶提交的搜索關鍵詞。用戶經過表單 get 方法提交的數據 Django 爲咱們保存在 request.GET
裏,這是一個相似於 Python 字典的對象,因此咱們使用 get
方法從字典裏取出鍵 q 對應的值,即用戶的搜索關鍵詞。這裏字典的鍵之因此叫 q 是由於咱們的表單中搜索框 input 的 name 屬性的值是 q,若是修改了 name 屬性的值,那麼這個鍵的名稱也要相應修改。
接下來咱們作了一個小小的校驗,若是用戶沒有輸入搜索關鍵詞而提交了表單,咱們就無需執行查詢,咱們給給用戶發一條錯誤提醒消息,這裏使用了 django messages 應用,這在 交流的橋樑:評論功能 中講過。而後將用戶重定向到首頁。這裏的 redirect 函數也在那篇教程中講過。
若是用戶輸入了搜索關鍵詞,咱們就經過 filter
方法從數據庫裏過濾出符合條件的全部文章。這裏的過濾條件是 title__icontains=q
,即 title 中包含(contains)關鍵字 q,前綴 i 表示不區分大小寫。這裏 icontains
是查詢表達式(Field lookups),咱們在以前也使用過其餘相似的查詢表達式,其用法是在模型須要篩選的屬性後面跟上兩個下劃線。Django 內置了不少查詢表達式,建議過一遍 Django 官方留個印象,瞭解每一個表達式的做用,之後碰到相關的需求就能夠快速定位到文檔查詢其用途 Field lookups。
此外咱們這裏從 from django.db.models 中引入了一個新的東西:Q 對象。Q 對象用於包裝查詢表達式,其做用是爲了提供複雜的查詢邏輯。例如這裏 Q(title__icontains=q) | Q(body__icontains=q)
表示標題(title)含有關鍵詞 q 或者正文(body)含有關鍵詞 q ,或邏輯使用 |
符號。若是不用 Q 對象,就只能寫成 title__icontains=q, body__icontains=q
,這就變成標題(title)含有關鍵詞 q 且正文(body)含有關鍵詞 q,就達不到咱們想要的目的。
有了視圖函數後記得把視圖函數映射到相應了 URL,以下。
blog/urls.py
urlpatterns = [
# 其餘 url 配置
path('search/', views.search, name='search'),
]
複製代碼
大功告成,在導航欄嘗試輸入一些關鍵詞,看看效果吧!
固然這樣的搜索功能是很是簡略的,難以知足一些複雜的搜索需求。編寫一個搜索引擎是一個大工程,好在 django-haystack 這款第三方 app 爲咱們完成了所有工做。使用它咱們能夠實現更加複雜的搜索功能,好比全文檢索、按搜索相關度排序、關鍵字高亮等等相似於百度搜索的功能,功能十分強大。固然其使用也會複雜一些,下一篇教程將向你們介紹 django-haystack 結合 Elasticsearch 搜索引擎的使用方法。
『講解開源項目系列』——讓對開源項目感興趣的人再也不畏懼、讓開源項目的發起者再也不孤單。跟着咱們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯繫咱們、加入咱們,讓更多人愛上開源、貢獻開源~