---
title: \[Django] - 玖-1、Search view
tags: webdevelopment
---
為了讓完成各個view的過程比較清晰,我把每個view都分成一個小節,方便自己回顧。
首先是search view
主要的功能是當按下搜尋按鈕時會去尋找某域名有某關鍵字的搜尋排名,完成後顯示名次
這裡使用的方式是google的api,我利用google的[programable search engine](https://developers.google.com/custom-search/v1/overview#prerequisites)建立了一個客製化的搜尋引擎,並調整參數讓他依照條件只會搜尋固定地區的搜尋內容,接著再使用api傳遞以及獲取資料。
首先先建立一個function用來送出請求跟獲取資料
在views.py中輸入以下程式碼
```code=python
# SEO rank function: query=要搜尋的關鍵字,targetLink=要搜尋的域名
def seorank(query, targetLink):
API_KEY = "輸入自己的API金鑰"
SEARCH_ENGINE_ID = "輸入自己的客制搜尋引擎"
# 調整參數,可參考google的文件
C2COFF = 0
SAFE = "active"
HL = "zh-TW"
LR = "lang_zh-TW"
# 從第幾頁開始搜尋
page, i = 1, 0
# 這個api最多只能搜尋100個結果,每次搜尋會得到10個結果
# 所以我們只會搜尋到第10頁,到第10頁就停止迴圈
while page <= 10:
start = (page - 1) * 10 + 1
# API
url = f"https://www.googleapis.com/customsearch/v1?key={API_KEY}&cx={SEARCH_ENGINE_ID}&hl={HL}&lr={LR}&c2coff={C2COFF}&safe={SAFE}&q={query}&start={start}"
# 使用requests依照API的網址將其轉為json格式並送出請求
data = req.get(url).json()
# 獲取items的部分,並宣告為search_items
search_items = data.get("items")
# 若search_items沒東西,印出Error,並回傳-1
if search_items == None:
print("Error: There is no search_items.")
return -1
# 若有,依序檢查裡面的link是否有我們想搜尋的域名
# i代表名次
else:
for search_item in search_items:
i+=1
if targetLink in search_item.get("link"):
return i
page+=1
# 如果不在前100則回傳101
return "101"
```
完成之後,來到search view
```code=python
# search view
def search(request):
combine_list = []
rank_list = []
# 這個功能只給已登入的使用者使用
if request.user.is_authenticated:
# 如果request的方法是POST,代表表單送出
if request.method=='POST':
# 獲取表單
form = SearchForm(request.POST)
# 檢查表單是否有效
if form.is_valid():
# 把各欄位的資料分離出來
data = form.cleaned_data
print(data)
form = SearchForm()
# 把要搜尋的關鍵字整理成列表
keyword_list = data['keyword'].split(',')
print(keyword_list)
# rank_list = [0 for i in keyword_list]
# print(rank_list)
for i, keyword in enumerate(keyword_list):
print(f"{i}, {keyword} is processing!")
rank_list.append(rank_search(keyword, data['domain']))
# 檢查目前使用者正在搜尋的域名以前有沒有搜尋過
# 有就直接取用該域名物件,沒有就建立一個
new_domain, created = Domain.objects.get_or_create(
user = request.user,
domain = data['domain']
)
print("Domain GET/CREATE")
if not created:
new_domain.save()
print("Domain CREATE")
# 利用zip把關鍵字列表跟排名列表一對一對應
combine_list = zip(keyword_list, rank_list)
print(combine_list)
# 依序檢查列表中的關鍵字是否曾經搜尋過
# 沒有搜尋過就建立一個新的,有的話就直接使用
for keyword, rank_value in combine_list:
keyword_obj, created = Keyword.objects.get_or_create(
domain = new_domain,
keyword = keyword
)
print("Keyword GET/CREATE")
if not created:
keyword_obj.save()
print("Keyword CREATE")
# 建立新的排名紀錄
new_rank_history = KeywordRankHistory(
keyword = keyword_obj,
rank = rank_value
)
new_rank_history.save()
print(f"Rank is saved.")
print(f"{keyword}:{rank_value}")
# 表單無效,則不做任何事情
else:
form = SearchForm()
data = {'domain':''}
keyword_list = []
rank_list = []
combine_list = zip(keyword_list, rank_list)
return render(request, 'ranking/search.html',
context = {'form':form,
'domain':data['domain'],
'combine_list':combine_list},)
# 沒登入,則跳轉回登入頁面
else:
return HttpResponseRedirect("login")
```
完成之後,來測試一下頁面是否可以正常打開
照理來說,應該會跳到登入頁面,因為我們還沒登入喔~
search view到這裡就完成了!
下一篇會完成顯示紀錄的功能,請大家保持耐心喔。
如果想先試試看登入,可以先跳到登入頁面和註冊頁面
完成後再回來完成也可以
謝謝大家的收看!
如果有任何想法或是問題歡迎寄信到 chantinghsien@gmail.com
可以一起討論和分享新知