摘要:接下來判斷是否為空。因此接下來執行。這個方法用于獲取字典中指定鍵名的鍵值第一個參數,如果該鍵名不存在,則返回第二個參數設定的默認值。當我們填寫好表單,點擊發布按鈕,表單就以方式被提交到相對路徑,對應的絕對路徑為。
前面的話
在Demo1里面,我們練習了如何部署應用、tornado框架的基本結構以及應用如何處理請求。
其實Demo1算不上一個博客啦。一個最基本的信息系統一定要包含對數據庫的增、刪、改和查。所以這次,我們來將Demo1升級為Demo2,添加上基本的增刪改查。
終于=。=在github上創建了項目,把源碼傳上去了。有需要的同學自己去下載吧。
https://github.com/cAntCheng/simple_tutorial_of_tornado
吶,還是把源碼在這里貼一下
demo.py
#!/usr/bin/env python # -*- coding: utf-8 -*- import os.path import tornado.auth import tornado.escape import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web from tornado.options import define, options import pymongo define("port", default=8002, help="run on the given port", type=int) class Application(tornado.web.Application): def __init__(self): handlers = [ (r"/", MainHandler), (r"/edit/([0-9Xx-]+)", EditHandler), (r"/add", EditHandler), (r"/delete/([0-9Xx-]+)", DelHandler), (r"/blog/([0-9Xx-]+)", BlogHandler), ] settings = dict( template_path=os.path.join(os.path.dirname(__file__), "templates"), static_path=os.path.join(os.path.dirname(__file__), "static"), debug=True, ) conn = pymongo.Connection("localhost", 27017) self.db = conn["demo2"] tornado.web.Application.__init__(self, handlers, **settings) class MainHandler(tornado.web.RequestHandler): def get(self): import time coll = self.application.db.blog blogs = coll.find().sort("id",pymongo.DESCENDING) self.render( "index.html", blogs = blogs, time = time, ) class EditHandler(tornado.web.RequestHandler): def get(self, id=None): blog = dict() if id: coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) self.render("edit.html", blog = blog) def post(self, id=None): import time coll = self.application.db.blog blog = dict() if id: blog = coll.find_one({"id": int(id)}) blog["title"] = self.get_argument("title", None) blog["content"] = self.get_argument("content", None) if id: coll.save(blog) else: last = coll.find().sort("id",pymongo.DESCENDING).limit(1) lastone = dict() for item in last: lastone = item blog["id"] = int(lastone["id"]) + 1 blog["date"] = int(time.time()) coll.insert(blog) self.redirect("/") class DelHandler(tornado.web.RequestHandler): def get(self, id=None): coll = self.application.db.blog if id: blog = coll.remove({"id": int(id)}) self.redirect("/") class BlogHandler(tornado.web.RequestHandler): def get(self, id=None): import time coll = self.application.db.blog if id: blog = coll.find_one({"id": int(id)}) self.render("blog.html", page_title = "我的博客", blog = blog, time = time, ) else: self.redirect("/") def main(): tornado.options.parse_command_line() http_server = tornado.httpserver.HTTPServer(Application()) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__": main()
index.html
{% autoescape None %}B06 Innovation Space
blog.html
{% autoescape None %}{{ page_title }}
edit.html
B06 Innovation Space
代碼回顧:
handlers = [ (r"/", MainHandler), (r"/edit/([0-9Xx-]+)", EditHandler), (r"/add", EditHandler), (r"/delete/([0-9Xx-]+)", DelHandler), (r"/blog/([0-9Xx-]+)", BlogHandler), ]
在Demo2中定義了5個handler,分別是
(r"/", MainHandler)->博客列表
(r"/edit/([0-9Xx-]+)", MainHandler)->編輯博客
(r"/add", MainHandler)->發表博客
(r"/delete/([0-9Xx-]+)", MainHandler)->刪除博客
(r"/blog/([0-9Xx-]+)", MainHandler)->查看博客
通過這五個handler,我們終于能寫出一個真正的博客了噢耶。
有沒有注意到/([0-9Xx-]+)!!!這是干嘛的呢?恩,這是一個url參數。這個正則表達式規定參數由0-9的數字和X組成。
在edit、delete和blog方法中,我們需要一個博客id參數來找到指定的博客進行響應操作,所以我們在這里添加了一個url參數。
代碼回顧:
class MainHandler(tornado.web.RequestHandler): def get(self): import time coll = self.application.db.blog blogs = coll.find().sort("id",pymongo.DESCENDING) self.render( "index.html", blogs = blogs, time = time, )
在MainHandler中,我們通過find()查詢所有的博客,并通過sort("id",pymongo.DESCENDING)對博客id進行倒序排序(因為id越大,博文就越新,那它就應該在越前面顯示嘛)。
同時載入了time模塊,方便我們在模板里輸出正確格式的時間。
代碼回顧:
{{ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(blog["date"]) ) }}
看看index.html,在輸出時間的這一行,調用了time模塊的strftime()方法,將在數據庫儲存的時間按照制定的格式%Y-%m-%d %H:%M:%S輸出。
注意:可以看到,在self.render()方法中,我們將time對象作為參數傳遞到模板中。
這樣我們才可以在模板中調用time對象的方法。
代碼回顧:
{% for blog in blogs %} ... {% end %}
通過for循環輸出博客列表。
來看看效果(不要在意里面亂七八糟的內容=。=):
代碼回顧:
(r"/add", EditHandler),
有沒有覺得奇怪=。=,為什么add(發表博客)調用的還是EditHandler。
解釋:
一般的博客系統,發表博客和編輯博客的模板(html文件)其實是一樣的。無非是編輯博客的模板里填充了博客的內容,而發表博客的模板是一個空表單。
因此我們常常把新增和編輯放在同一個方法里處理。具體的處理方法我們下面繼續聊。
代碼回顧:
class EditHandler(tornado.web.RequestHandler): def get(self, id=None): blog = dict() if id: coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) self.render("edit.html", blog = blog)
在get方法中,我們新建了一個空字典blog。接下來判斷id是否為空。我們通過判斷id是否為空來選擇下一步是編輯還是新增。
代碼回顧:
思考一下業務邏輯,當我們點擊首頁發布按鈕,即訪問http://127.0.0.1:8002/add,由EditHandler執行get方法。
代碼回顧:
def get(self, id=None):
因為沒有傳遞url參數,所以id賦值為默認值None。
代碼回顧:
if id: coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) self.render("edit.html", blog = blog)
因為id = None,所以if id:為false。因此接下來執行self.render("edit.html",blog = blog)。
代碼回顧:
{% if blog.get("id", None) %}
文章標題:
文章正文:
在edit.html中,我們通過判斷blog.get("id", None)的值是否為None來輸出不同的form標簽。
dict.get("key","Defalt")這個方法用于獲取字典中指定鍵名的鍵值(第一個參數),如果該鍵名不存在,則返回第二個參數設定的默認值。
要調用這個方法,我們必須有一個字典可以查找。所以在EditHandler的get方法中,我們定義了一個空字典:blog(還記得嗎?回頭看一下代碼吧。)
繼續剛才的業務邏輯,我們渲染了edit.html,并將空字典:blog作為參數傳遞到模板文件中。所以blog.get("id", None) == None,所以輸出
下面的{{ blog.get("title", "") }}和{{ blog.get("content", "") }},同上,均為空字符串。所以我們最終得到了一個空表單頁面,也就是我們的發布博客頁面。
當我們填寫好表單,點擊發布按鈕,表單就以POST方式被提交到/add(相對路徑,對應的絕對路徑為http://127.0.0.1:8002/add)。這時候EditHandler執行post方法。
代碼回顧:
def post(self, id=None): import time coll = self.application.db.blog blog = dict() if id: blog = coll.find_one({"id": int(id)}) blog["title"] = self.get_argument("title", None) blog["content"] = self.get_argument("content", None) if id: coll.save(blog) else: last = coll.find().sort("id",pymongo.DESCENDING).limit(1) lastone = dict() for item in last: lastone = item blog["id"] = int(lastone["id"]) + 1 blog["date"] = int(time.time()) coll.insert(blog) self.redirect("/")
在post方法中,同樣的邏輯判斷執行新增還是編輯。
代碼回顧:
blog["title"] = self.get_argument("title", None) blog["content"] = self.get_argument("content", None)
將獲取的表單填充到空字典:blog中,然后調用coll.insert(blog)方法向數據庫中插入文檔。
誒誒誒,等等,好像插入之前還有好幾行啊!!
好吧=。=這幾行代碼是用來生成新博客id的。我們的博客需要一個id來標識身份,所以我們給每一篇博客設置一個id。一般就是用一個從1開始自增的整數作為id啦。
解釋:
因為mongodb不像mysql那樣可以設置自增字段,所以我們需要自己生成自增的id(查過資料應該是有辦法設置自增,但是文檔沒太看明白=。=就當沒有辦法吧。除了文檔中的辦法,我查了好久,發現都是靠自己寫函數生成自增的id,大家有興趣可以自己去查一下。在這里我就用自己的方法了。)
我的方法是這樣的:
last = coll.find().sort("id",pymongo.DESCENDING).limit(1)倒序查詢數據庫獲取最后id最大的那一條記錄。因為find()函數返回的結果是一個數組?所以要用for循環取值(因為只查詢了一條記錄,所以用一個循環也不會太奢侈吧啦啦啦)。
blog["id"] = int(lastone["id"]) + 1將最大id加1賦值給新博客的id。因為mongodb在存整型數的時候好像會默認存為浮點型(具體可以自行百度),所以用int()方法處理lastone["id"]保證我們處理過程中數據類型的正確。
好了,這樣我們終于成功新增了一篇博客!!!
查當我們在首頁點擊某一篇博客的標題的時候,比如點擊第二篇,我們會訪問http://127.0.0.1:8002/blog/2,進入到這個頁面:
這個過程是這樣的:/blog對應BlogHandler,執行get方法。
代碼回顧:
class BlogHandler(tornado.web.RequestHandler): def get(self, id=None): import time coll = self.application.db.blog if id: blog = coll.find_one({"id": int(id)}) self.render("blog.html", page_title = "我的博客", blog = blog, time = time, ) else: self.redirect("/")
if判斷id是否存在,不存在則跳轉到首頁。我們這里get方法獲取到url參數,因此id=2。blog = coll.find_one({"id": int(id)})查詢該博客并渲染博客頁面。
這樣,我們就完成了博客查看的功能。
改留一個小問題。
因為這個demo是剛開始學tornado的時候寫的,所以代碼其實寫得很糟糕。
BlogHandler可能這樣寫會更好一點,初學的同學看一看,思考一下為什么。我就不改demo里的代碼了。class BlogHandler(tornado.web.RequestHandler): def get(self, id=0): import time coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) if blog: self.render("blog.html", page_title = "我的博客", blog = blog, time = time, ) else: self.redirect("/")
代碼回顧:
class EditHandler(tornado.web.RequestHandler): def get(self, id=None): blog = dict() if id: coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) self.render("edit.html", blog = blog) def post(self, id=None): import time coll = self.application.db.blog blog = dict() if id: blog = coll.find_one({"id": int(id)}) blog["title"] = self.get_argument("title", None) blog["content"] = self.get_argument("content", None) if id: coll.save(blog) else: last = coll.find().sort("id",pymongo.DESCENDING).limit(1) lastone = dict() for item in last: lastone = item blog["id"] = int(lastone["id"]) + 1 blog["date"] = int(time.time()) coll.insert(blog) self.redirect("/")
自己看,就不多說了=。=
刪刪除操作的邏輯是,傳遞博客id給DelHandler,然后調用remove()方法從數據庫刪除指定博客。
代碼回顧:
class DelHandler(tornado.web.RequestHandler): def get(self, id=None): coll = self.application.db.blog if id: blog = coll.remove({"id": int(id)}) self.redirect("/")
<( ̄ˇ ̄)/相信聰明的你已經看懂了!
總結至此,我們練習了mongodb的增刪改查,也實現了應用的增刪改查。
當然這個Demo還有很多需要改進的地方,比如:
構造形如http://127.0.0.1:8002/delete?id=2的鏈接,通過get方法傳遞參數。
給我們的表單加上格式驗證。
同學們可以自己稍作修改嘗試一下。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/18733.html
摘要:接下來判斷是否為空。因此接下來執行。這個方法用于獲取字典中指定鍵名的鍵值第一個參數,如果該鍵名不存在,則返回第二個參數設定的默認值。當我們填寫好表單,點擊發布按鈕,表單就以方式被提交到相對路徑,對應的絕對路徑為。 前面的話 在Demo1里面,我們練習了如何部署應用、tornado框架的基本結構以及應用如何處理請求。 其實Demo1算不上一個博客啦。一個最基本的信息系統一定要包含對數據...
摘要:學習筆記七數學形態學關注的是圖像中的形狀,它提供了一些方法用于檢測形狀和改變形狀。學習筆記十一尺度不變特征變換,簡稱是圖像局部特征提取的現代方法基于區域圖像塊的分析。本文的目的是簡明扼要地說明的編碼機制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來看這樣一個提問: pyth...
摘要:學的過程中查閱了無數資料,也收獲了一些經驗,所以希望總結出一份簡易入門教程供初學者參考。完整的教程將盡可能遵循下面的目錄順序。安裝的安裝也很簡單。搭建簡單服務器表示不是必要的這里僅以做示范,其他系統操作方法類似。 前言: 這兩天在學著用Python + Tornado +MongoDB來做Web開發(哈哈哈這個詞好高端)。學的過程中查閱了無數資料,也收獲了一些經驗,所以希望總結出一份...
摘要:學的過程中查閱了無數資料,也收獲了一些經驗,所以希望總結出一份簡易入門教程供初學者參考。完整的教程將盡可能遵循下面的目錄順序。安裝的安裝也很簡單。搭建簡單服務器表示不是必要的這里僅以做示范,其他系統操作方法類似。 前言: 這兩天在學著用Python + Tornado +MongoDB來做Web開發(哈哈哈這個詞好高端)。學的過程中查閱了無數資料,也收獲了一些經驗,所以希望總結出一份...
閱讀 3236·2021-11-24 09:39
閱讀 2912·2021-09-09 11:34
閱讀 3190·2021-09-07 09:58
閱讀 2299·2019-08-30 13:07
閱讀 2859·2019-08-29 15:09
閱讀 1560·2019-08-29 13:01
閱讀 2300·2019-08-26 12:18
閱讀 1911·2019-08-26 10:28