Django 文章搜尋實作解析:if search_query 與 OR 查詢的正確打開方式
✍️ 作者:如如(ru)
📅 發布於 2026年01月06日 23:36
✏️ 更新於 2026年01月06日 23:57
📖 閱讀時間: 10 分鐘
在實作部落格文章列表時,「搜尋功能」幾乎是一定會遇到的需求。
看似只有幾行的 Django ORM,其實背後藏了不少設計細節。
這篇文章會完整說明:
- 為什麼要先判斷 `if search_query`
- `request.GET.get('q', '')` 的設計用意
- `icontains` 在 ORM 中的實際行為
- 使用 OR(`|`)合併查詢的意義
- 常見不良寫法與推薦改法
---
## 一、實際範例程式碼
```python
# 取得搜尋關鍵字
search_query = request.GET.get('q', '')
# 取得所有文章
articles = Article.objects.all()
# 如果有搜尋關鍵字,過濾文章
if search_query:
articles = articles.filter(
title__icontains=search_query
) | articles.filter(
content__icontains=search_query
)
```
---
## 二、為什麼要使用 request.GET.get('q', '')
request.GET 是 Django 提供的 QueryDict,行為類似 Python 的 dict。
`.get(key, default)` 的規則是:
- key 存在 → 回傳值
- key 不存在 → 回傳 default
使用空字串而不是 None,可以讓後續 ORM 操作更安全、直覺。
---
## 三、if search_query 的判斷意義
在 Python 中:
- 空字串是 False
- 非空字串是 True
因此這行等同於判斷「使用者是否真的輸入搜尋關鍵字」。
---
## 四、icontains 的意義
`icontains` 表示「不分大小寫的包含」。
概念上等同於 SQL:
```sql
WHERE title ILIKE '%keyword%'
```
---
## 五、使用 | 合併 QuerySet(OR)
`|` 代表 QuerySet 的聯集(OR),
表示只要符合其中一個條件即可。
---
## 六、潛在問題
- 可讀性差
- 擴充困難
- 可能產生重複資料(需 distinct)
---
## 七、推薦寫法:使用 Q()
```python
from django.db.models import Q
if search_query:
articles = articles.filter(
Q(title__icontains=search_query) |
Q(content__icontains=search_query)
).distinct()
```
---
## 八、完整實務範例
```python
from django.db.models import Q
def home(request):
search_query = request.GET.get('q', '').strip()
articles = Article.objects.all().order_by('-created_at')
if search_query:
articles = articles.filter(
Q(title__icontains=search_query) |
Q(content__icontains=search_query)
).distinct()
return render(request, 'blog/home.html', {
'articles': articles,
'search_query': search_query,
})
```
---
## 九、結語
搜尋功能的重點不在於能不能跑,
而在於是否好維護、好擴充、好理解。
當你開始在意這些細節,
代表你已經在用工程師的角度設計 Django 應用程式。
💬 留言 (0)
請先登入後再發表留言
目前還沒有留言,快來搶沙發吧!