Download - tangowithdjango - Ch12
TwD Chapter 12
Adding External Search Functionality
asika KuoFor Django Summer
Django Summer 2
12. Adding External Search Functionality
● 本章要利用 Bing API替 APP增加搜尋功能
Django Summer 3
12.1. The Bing Search API
● 把用 Bing搜尋到的資料顯示在自己的 APP裡● Bing伺服器回傳的 result可以是 XML或 JSON(可以自己指定)
Django Summer 4
12.1.1. Registering for a Bing API Key
● 註冊 MS的帳號(可以直接用 hotmail的)– https://account.windowsazure.com
● 到Windows Azure Marketplace Bing Search API page訂閱免費版搜尋 API服務– 5,000 Transactions/month
Django Summer 5
12.2. Adding Search Functionality
● 建立 rango/bing_search.py
Django Summer 6
12.2. Adding Search Functionality
● 根據 API的規定準備好我們要送出的request字串
def run_query(search_terms): root_url = 'https://api.datamarket.azure.com/Bing/Search/' source = 'Web'
results_per_page = 10 offset = 0
query = "'{0}'".format(search_terms) query = urllib.quote(query)
search_url = "{0}{1}?$format=json&$top={2}&$skip={3}&Query={4}".format( root_url, source, results_per_page, offset, query)
Django Summer 7
12.2. Adding Search Functionality
● 利用 urllib2的password manager在送出的 HTTP request header中加入我們剛申請好的API Key資訊
●
# Setup authentication with the Bing servers.
# The username MUST be a blank string, and put in your API key!
username = ''
bing_api_key = '<api_key>'
# Create a 'password manager' which handles authentication for us.
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None, search_url, username, bing_api_key)
Django Summer 8
● HTTP Basic Authentication
– 在用戶端發送 request時一併於 HTTP header提供用戶名和密碼的一種簡易認證方式
– 預設會將 <username>:<password>用 Base64編碼後送出● 不是為了安全性而是為了轉換掉與 HTTP不相容的字元
● Bing規定的 API Key認證方式
– Username: 空字串– Password: 申請到的 API Key
Django Summer 9
12.2. Adding Search Functionality
● 用 urllib2.openurl()連同 query string 和認證資訊一起送出
● 接到的 response 會是字串格式的 JSON
● 用 json.loads() 轉成python dictionary
# Prepare for connecting to Bing's servers.
handler = urllib2.HTTPBasicAuthHandler(password_mgr)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
# Connect to the server and read the response generated.
response = urllib2.urlopen(search_url).read()
# Convert the string response to a Python dictionary object.
json_response = json.loads(response)
# Loop through each page returned, populating out results list.
for result in json_response['d']['results']:
results.append({
'title': result['Title'],
'link': result['Url'],
'summary': result['Description']})
Django Summer 10
12.3. Putting Search into Rango
● 建立 templates/rango/search.html
– 如果有傳入result_list 就把內容 render 到頁面上
{% if result_list %}
<!-- Display search results in an ordered list -->
<div style="clear: both;">
<ol>
{% for result in result_list %}
<li>
<strong><a href="{{ result.link }}">{{ result.title }}</a></strong><br />
<em>{{ result.summary }}</em>
</li>
{% endfor %}
</ol>
</div>
{% endif %}
Django Summer 11
12.3.2. Adding the View
def search(request):
context = RequestContext(request)
result_list = []
if request.method == 'POST':
query = request.POST['query'].strip()
if query:
# Run our Bing function to get the results list!
result_list = run_query(query)
return render_to_response('rango/search.html', {'result_list': result_list}, context)
Django Summer 12
處理 Unicode
● run_query() 預設處理的格式是 str
– query = "'{0}'".format(search_terms)● 從前端傳回來的 query string 是 unicode
– 包含英文以外的字元, format() 就會發生UnicodeEncodeError
● 解法– 呼叫 unicode 的 format()
● query = u"'{0}'".format(search_terms)●
Django Summer 13
處理 Unicode
● urllib.quote()傳入 unicode字串發生 KeyError● 解法
– 把 query字串編碼為UTF-8– query = urllib.quote(query.encode('utf-8'))