摘要:接下來(lái)判斷是否為空。因此接下來(lái)執(zhí)行。這個(gè)方法用于獲取字典中指定鍵名的鍵值第一個(gè)參數(shù),如果該鍵名不存在,則返回第二個(gè)參數(shù)設(shè)定的默認(rèn)值。當(dāng)我們填寫好表單,點(diǎn)擊發(fā)布按鈕,表單就以方式被提交到相對(duì)路徑,對(duì)應(yīng)的絕對(duì)路徑為。
前面的話
在Demo1里面,我們練習(xí)了如何部署應(yīng)用、tornado框架的基本結(jié)構(gòu)以及應(yīng)用如何處理請(qǐng)求。
其實(shí)Demo1算不上一個(gè)博客啦。一個(gè)最基本的信息系統(tǒng)一定要包含對(duì)數(shù)據(jù)庫(kù)的增、刪、改和查。所以這次,我們來(lái)將Demo1升級(jí)為Demo2,添加上基本的增刪改查。
終于=。=在github上創(chuàng)建了項(xiàng)目,把源碼傳上去了。有需要的同學(xué)自己去下載吧。
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個(gè)handler,分別是
(r"/", MainHandler)->博客列表
(r"/edit/([0-9Xx-]+)", MainHandler)->編輯博客
(r"/add", MainHandler)->發(fā)表博客
(r"/delete/([0-9Xx-]+)", MainHandler)->刪除博客
(r"/blog/([0-9Xx-]+)", MainHandler)->查看博客
通過(guò)這五個(gè)handler,我們終于能寫出一個(gè)真正的博客了噢耶。
有沒有注意到/([0-9Xx-]+)!??!這是干嘛的呢?恩,這是一個(gè)url參數(shù)。這個(gè)正則表達(dá)式規(guī)定參數(shù)由0-9的數(shù)字和X組成。
在edit、delete和blog方法中,我們需要一個(gè)博客id參數(shù)來(lái)找到指定的博客進(jìn)行響應(yīng)操作,所以我們?cè)谶@里添加了一個(gè)url參數(shù)。
代碼回顧:
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中,我們通過(guò)find()查詢所有的博客,并通過(guò)sort("id",pymongo.DESCENDING)對(duì)博客id進(jìn)行倒序排序(因?yàn)?b>id越大,博文就越新,那它就應(yīng)該在越前面顯示嘛)。
同時(shí)載入了time模塊,方便我們?cè)谀0謇镙敵稣_格式的時(shí)間。
代碼回顧:
{{ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(blog["date"]) ) }}
看看index.html,在輸出時(shí)間的這一行,調(diào)用了time模塊的strftime()方法,將在數(shù)據(jù)庫(kù)儲(chǔ)存的時(shí)間按照制定的格式%Y-%m-%d %H:%M:%S輸出。
注意:可以看到,在self.render()方法中,我們將time對(duì)象作為參數(shù)傳遞到模板中。
這樣我們才可以在模板中調(diào)用time對(duì)象的方法。
代碼回顧:
{% for blog in blogs %} ... {% end %}
通過(guò)for循環(huán)輸出博客列表。
來(lái)看看效果(不要在意里面亂七八糟的內(nèi)容=。=):
代碼回顧:
(r"/add", EditHandler),
有沒有覺得奇怪=。=,為什么add(發(fā)表博客)調(diào)用的還是EditHandler。
解釋:
一般的博客系統(tǒng),發(fā)表博客和編輯博客的模板(html文件)其實(shí)是一樣的。無(wú)非是編輯博客的模板里填充了博客的內(nèi)容,而發(fā)表博客的模板是一個(gè)空表單。
因此我們常常把新增和編輯放在同一個(gè)方法里處理。具體的處理方法我們下面繼續(xù)聊。
代碼回顧:
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方法中,我們新建了一個(gè)空字典blog。接下來(lái)判斷id是否為空。我們通過(guò)判斷id是否為空來(lái)選擇下一步是編輯還是新增。
代碼回顧:
思考一下業(yè)務(wù)邏輯,當(dāng)我們點(diǎn)擊首頁(yè)發(fā)布按鈕,即訪問http://127.0.0.1:8002/add,由EditHandler執(zhí)行get方法。
代碼回顧:
def get(self, id=None):
因?yàn)闆]有傳遞url參數(shù),所以id賦值為默認(rèn)值None。
代碼回顧:
if id: coll = self.application.db.blog blog = coll.find_one({"id": int(id)}) self.render("edit.html", blog = blog)
因?yàn)?b>id = None,所以if id:為false。因此接下來(lái)執(zhí)行self.render("edit.html",blog = blog)。
代碼回顧:
{% if blog.get("id", None) %}
在edit.html中,我們通過(guò)判斷blog.get("id", None)的值是否為None來(lái)輸出不同的form標(biāo)簽。
dict.get("key","Defalt")這個(gè)方法用于獲取字典中指定鍵名的鍵值(第一個(gè)參數(shù)),如果該鍵名不存在,則返回第二個(gè)參數(shù)設(shè)定的默認(rèn)值。
要調(diào)用這個(gè)方法,我們必須有一個(gè)字典可以查找。所以在EditHandler的get方法中,我們定義了一個(gè)空字典:blog(還記得嗎?回頭看一下代碼吧。)
繼續(xù)剛才的業(yè)務(wù)邏輯,我們渲染了edit.html,并將空字典:blog作為參數(shù)傳遞到模板文件中。所以blog.get("id", None) == None,所以輸出。
下面的{{ blog.get("title", "") }}和{{ blog.get("content", "") }},同上,均為空字符串。所以我們最終得到了一個(gè)空表單頁(yè)面,也就是我們的發(fā)布博客頁(yè)面。
當(dāng)我們填寫好表單,點(diǎn)擊發(fā)布按鈕,表單就以POST方式被提交到/add(相對(duì)路徑,對(duì)應(yīng)的絕對(duì)路徑為http://127.0.0.1:8002/add)。這時(shí)候EditHandler執(zhí)行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方法中,同樣的邏輯判斷執(zhí)行新增還是編輯。
代碼回顧:
blog["title"] = self.get_argument("title", None) blog["content"] = self.get_argument("content", None)
將獲取的表單填充到空字典:blog中,然后調(diào)用coll.insert(blog)方法向數(shù)據(jù)庫(kù)中插入文檔。
誒誒誒,等等,好像插入之前還有好幾行?。?!
好吧=。=這幾行代碼是用來(lái)生成新博客id的。我們的博客需要一個(gè)id來(lái)標(biāo)識(shí)身份,所以我們給每一篇博客設(shè)置一個(gè)id。一般就是用一個(gè)從1開始自增的整數(shù)作為id啦。
解釋:
因?yàn)?b>mongodb不像mysql那樣可以設(shè)置自增字段,所以我們需要自己生成自增的id(查過(guò)資料應(yīng)該是有辦法設(shè)置自增,但是文檔沒太看明白=。=就當(dāng)沒有辦法吧。除了文檔中的辦法,我查了好久,發(fā)現(xiàn)都是靠自己寫函數(shù)生成自增的id,大家有興趣可以自己去查一下。在這里我就用自己的方法了。)
我的方法是這樣的:
last = coll.find().sort("id",pymongo.DESCENDING).limit(1)倒序查詢數(shù)據(jù)庫(kù)獲取最后id最大的那一條記錄。因?yàn)?b>find()函數(shù)返回的結(jié)果是一個(gè)數(shù)組?所以要用for循環(huán)取值(因?yàn)橹徊樵兞艘粭l記錄,所以用一個(gè)循環(huán)也不會(huì)太奢侈吧啦啦啦)。
blog["id"] = int(lastone["id"]) + 1將最大id加1賦值給新博客的id。因?yàn)?b>mongodb在存整型數(shù)的時(shí)候好像會(huì)默認(rèn)存為浮點(diǎn)型(具體可以自行百度),所以用int()方法處理lastone["id"]保證我們處理過(guò)程中數(shù)據(jù)類型的正確。
好了,這樣我們終于成功新增了一篇博客?。?!
查當(dāng)我們?cè)谑醉?yè)點(diǎn)擊某一篇博客的標(biāo)題的時(shí)候,比如點(diǎn)擊第二篇,我們會(huì)訪問http://127.0.0.1:8002/blog/2,進(jìn)入到這個(gè)頁(yè)面:
這個(gè)過(guò)程是這樣的:/blog對(duì)應(yīng)BlogHandler,執(zhí)行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是否存在,不存在則跳轉(zhuǎn)到首頁(yè)。我們這里get方法獲取到url參數(shù),因此id=2。blog = coll.find_one({"id": int(id)})查詢?cè)摬┛筒?b>渲染博客頁(yè)面。
這樣,我們就完成了博客查看的功能。
改留一個(gè)小問題。
因?yàn)檫@個(gè)demo是剛開始學(xué)tornado的時(shí)候?qū)懙模源a其實(shí)寫得很糟糕。
BlogHandler可能這樣寫會(huì)更好一點(diǎn),初學(xué)的同學(xué)看一看,思考一下為什么。我就不改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("/")
自己看,就不多說(shuō)了=。=
刪刪除操作的邏輯是,傳遞博客id給DelHandler,然后調(diào)用remove()方法從數(shù)據(jù)庫(kù)刪除指定博客。
代碼回顧:
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("/")
<( ̄ˇ ̄)/相信聰明的你已經(jīng)看懂了!
總結(jié)至此,我們練習(xí)了mongodb的增刪改查,也實(shí)現(xiàn)了應(yīng)用的增刪改查。
當(dāng)然這個(gè)Demo還有很多需要改進(jìn)的地方,比如:
構(gòu)造形如http://127.0.0.1:8002/delete?id=2的鏈接,通過(guò)get方法傳遞參數(shù)。
給我們的表單加上格式驗(yàn)證。
同學(xué)們可以自己稍作修改嘗試一下。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/37511.html
摘要:接下來(lái)判斷是否為空。因此接下來(lái)執(zhí)行。這個(gè)方法用于獲取字典中指定鍵名的鍵值第一個(gè)參數(shù),如果該鍵名不存在,則返回第二個(gè)參數(shù)設(shè)定的默認(rèn)值。當(dāng)我們填寫好表單,點(diǎn)擊發(fā)布按鈕,表單就以方式被提交到相對(duì)路徑,對(duì)應(yīng)的絕對(duì)路徑為。 前面的話 在Demo1里面,我們練習(xí)了如何部署應(yīng)用、tornado框架的基本結(jié)構(gòu)以及應(yīng)用如何處理請(qǐng)求。 其實(shí)Demo1算不上一個(gè)博客啦。一個(gè)最基本的信息系統(tǒng)一定要包含對(duì)數(shù)據(jù)...
摘要:學(xué)習(xí)筆記七數(shù)學(xué)形態(tài)學(xué)關(guān)注的是圖像中的形狀,它提供了一些方法用于檢測(cè)形狀和改變形狀。學(xué)習(xí)筆記十一尺度不變特征變換,簡(jiǎn)稱是圖像局部特征提取的現(xiàn)代方法基于區(qū)域圖像塊的分析。本文的目的是簡(jiǎn)明扼要地說(shuō)明的編碼機(jī)制,并給出一些建議。 showImg(https://segmentfault.com/img/bVRJbz?w=900&h=385); 前言 開始之前,我們先來(lái)看這樣一個(gè)提問: pyth...
摘要:學(xué)的過(guò)程中查閱了無(wú)數(shù)資料,也收獲了一些經(jīng)驗(yàn),所以希望總結(jié)出一份簡(jiǎn)易入門教程供初學(xué)者參考。完整的教程將盡可能遵循下面的目錄順序。安裝的安裝也很簡(jiǎn)單。搭建簡(jiǎn)單服務(wù)器表示不是必要的這里僅以做示范,其他系統(tǒng)操作方法類似。 前言: 這兩天在學(xué)著用Python + Tornado +MongoDB來(lái)做Web開發(fā)(哈哈哈這個(gè)詞好高端)。學(xué)的過(guò)程中查閱了無(wú)數(shù)資料,也收獲了一些經(jīng)驗(yàn),所以希望總結(jié)出一份...
摘要:學(xué)的過(guò)程中查閱了無(wú)數(shù)資料,也收獲了一些經(jīng)驗(yàn),所以希望總結(jié)出一份簡(jiǎn)易入門教程供初學(xué)者參考。完整的教程將盡可能遵循下面的目錄順序。安裝的安裝也很簡(jiǎn)單。搭建簡(jiǎn)單服務(wù)器表示不是必要的這里僅以做示范,其他系統(tǒng)操作方法類似。 前言: 這兩天在學(xué)著用Python + Tornado +MongoDB來(lái)做Web開發(fā)(哈哈哈這個(gè)詞好高端)。學(xué)的過(guò)程中查閱了無(wú)數(shù)資料,也收獲了一些經(jīng)驗(yàn),所以希望總結(jié)出一份...
閱讀 1088·2021-11-24 09:39
閱讀 1319·2021-11-18 13:18
閱讀 2462·2021-11-15 11:38
閱讀 1840·2021-09-26 09:47
閱讀 1641·2021-09-22 15:09
閱讀 1634·2021-09-03 10:29
閱讀 1522·2019-08-29 17:28
閱讀 2961·2019-08-29 16:30