先求有再求好,我們先以陽春麵版的機器人文字查詢與回覆方式,帶各位引入門與了解邏輯,下一篇會介紹漂漂亮亮版,讓你的機器人看起來很有格局~
這邊提供三筆範例課程評價資料供讀者使用,欄位依序為類型、課名、老師名、投稿者、內容、投稿學期,其內容為真實投稿內容改編,而其中兩筆評價描寫的課程名稱相同,以便進行程式教學。
先在 http://127.0.0.1:8000/admin/chatbot/course/
或是直接進入後台 courses
Table 手動新增三筆資料,讓資料庫開始有了生氣~
為什麼沒有對應的評價,會選擇以不回應處理,而不是回應「查不到」呢?因為在做小生物 LINE Bot 的時候,我們發現到許多學生會將機器人作為備忘錄使用,如果不斷回覆反而造成使用困擾,所以在這邊選擇了不回覆,當然,這只是觀察使用者使用習慣後的一種選擇,在這裡也提醒開發者,除了技術外,使用者體驗也是非常重要的。
views.py
接收訊息與引入資料表進行搜尋回覆hulolo
> hulolo
> models.py
的資料表類別引入,再將 handle_message
函式原本貓貓的內容做移除,首先從變數 event
中取得使用者所發送的文字:
# 此檔案位置: hulolo > chatbot > views.py
from .models import *
@parser.add(MessageEvent, message=TextMessage)
def handle_message(event):
user_message = event.message.text # 取得使用者發送的文字
-
判定使用者想要進行評價搜尋,因為此時搜尋評價的規則是「王小明-海洋生命科學導論」,無論如何都會有 -
,並以 -
為界做字串分割,前者為老師,後者為課名:
# 接續上一步程式碼
if "-" in user_message:
teacher_name = user_message.split("-")[0]
course_name = user_message.split("-")[1]
teacher_name
以及 course_name
,以此當作關鍵字進行搜尋,這邊會使用到一個資料庫 ORM 查詢的方式,Course.objects.filter
代表的是從 Course
類別/資料表中進行過濾,過濾的條件則是希望欄位 teacher_name
等於 teacher_name;欄位 course_name
等於 course_name,注意兩變數雖然一樣但是代表意義不同,前者是來自 models.py
field 所命名,後者則是來自第 2 步所宣告的變數:
# 接續上一步程式碼
filtered_courses = Course.objects.filter(teacher_name=teacher_name, course_name=course_name)[:5]
LINE 官方文件規定一次回覆最多為 5 則,因此這邊取的資料為最多前 5 筆。
filtered_courses
,可以透過 exists()
判斷裡面有沒有查詢到,若有就可以準備打包給使用者,這邊使用了迴圈是因為可能搜尋到的評價不只一則:
# 接續上一步程式碼
if filtered_courses.exists():
messages = []
for course in filtered_courses:
messages.append(TextSendMessage(
text=f"""
課程: {course.course_name}\
評價: {course.feedback_content}
"""))
line_bot_api.reply_message
準備回覆:
# 接續上一步程式碼
line_bot_api.reply_message(
event.reply_token,
messages #回覆所有 messages 陣列中的值
)
else
加上了 print("Empty")
,這樣會一查無此評價就可以在 Terminal 顯示,讓開發的你有一些安全感,至少不是壞了,其 handle_message
所有程式碼如下:
@parser.add(MessageEvent, message=TextMessage)
def handle_message(event):
user_message = event.message.text # 取得使用者發送的文字
if "-" in user_message:
teacher_name = user_message.split("-")[0]
course_name = user_message.split("-")[1]
filtered_courses = Course.objects.filter(teacher_name=teacher_name, course_name=course_name)[:5]
if filtered_courses.exists():
messages = []
for course in filtered_courses:
messages.append(TextSendMessage(
text=f"""課程: {course.course_name}\
評價: {course.feedback_content}
"""))
line_bot_api.reply_message(
event.reply_token,
messages
)
else:
print("Empty")
當輸入 王小明-海洋生命科學導論 就會得到一筆訊息回覆,輸入 吳小峰-特殊教育學生評量 則會收到兩筆訊息回覆,這樣就對啦~
@parser.add(MessageEvent, message=TextMessage)
是一種監聽的裝飾器,每當使用者發送 TextMessage
文字類型訊息的時候,就會請裝飾器下面的 handle_message
做處理,換言之也可以監聽圖片、影片、聲音等類型。Course.objects.filter
與沒有介紹的 Course.objects.get
都是常用的取得資料方式,前者無論有無結果都會回傳;而 .objects.get
只允許一個結果回來,如果多個就會跳 Exception
,適用在預期結果只有唯一,例如 id 或是身分證字號具有唯一性的搜尋條件,其效率會較高。line_bot_api.reply_message
中的 event.reply_token
是每一封使用者發送訊息時,LINE 轉傳過來的識別碼,需要在數秒內 帶著要回的訊息與識別碼回覆給 LINE 伺服器,使用者才會成功收到我們要給的訊息,且識別碼只能使用一次。可以想看看如果識別碼不會過期的話,那我們就可以一直一直吵對方了,這樣很快就天下大亂了: D在這篇文章中,我們學會了:
objects.filter
篩選資料表的方式event.message.text
接收使用者訊息與解讀的方法messages
可以是一個陣列,最多五個回覆給使用者TextSendMessage
回覆訊息