開源地址:https://github.com/leebingbin/Python3.WebAPP.Blog前端
在繼續工做前,注意到每次修改Python代碼,都必須在命令行先Ctrl-C中止服務器,再重啓,改動才能生效。在開發階段,天天都要修改、保存幾十次代碼,每次保存都手動來這麼一下很是麻煩,嚴重地下降了咱們的開發效率。
有沒有辦法讓服務器檢測到代碼修改後自動從新加載呢?Django的開發環境在Debug模式下就能夠作到自動從新加載,若是咱們編寫的服務器也能實現這個功能,就能大大提高開發效率。 python
惋惜的是,Django沒把這個功能獨立出來,不用Django就享受不到,怎麼辦?其實Python自己提供了從新載入模塊的功能,但不是全部模塊都能被從新載入。另外一種思路是檢測www目錄下的代碼改動,一旦有改動,就自動重啓服務器。git
按照這個思路,咱們能夠編寫一個輔助程序pymonitor.py,讓它啓動wsgiapp.py,並時刻監控www目錄下的代碼改動,有改動時,先把當前wsgiapp.py進程殺掉,再重啓,就完成了服務器進程的自動重啓。github
要監控目錄文件的變化,咱們也無需本身手動定時掃描,Python的第三方庫watchdog能夠利用操做系統的API來監控目錄文件的變化,併發送通知。咱們先用pip安裝:web
$ pip3 install watchdog
利用watchdog接收文件變化的通知,若是是.py文件,就自動重啓wsgiapp.py進程。後端
利用Python自帶的subprocess實現進程的啓動和終止,並把輸入輸出重定向到當前進程的輸入輸出中:api
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'libingbin2015@aliyun.com' import os, sys, time, subprocess from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler def log(s): print('[Monitor] %s' % s) class MyFileSystemEventHander(FileSystemEventHandler): def __init__(self, fn): super(MyFileSystemEventHander, self).__init__() self.restart = fn def on_any_event(self, event): if event.src_path.endswith('.py'): log('Python source file changed: %s' % event.src_path) self.restart() command = ['echo', 'ok'] process = None def kill_process(): global process if process: log('Kill process [%s]...' % process.pid) process.kill() process.wait() log('Process ended with code %s.' % process.returncode) process = None def start_process(): global process, command log('Start process %s...' % ' '.join(command)) process = subprocess.Popen(command, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr) def restart_process(): kill_process() start_process() def start_watch(path, callback): observer = Observer() observer.schedule(MyFileSystemEventHander(restart_process), path, recursive=True) observer.start() log('Watching directory %s...' % path) start_process() try: while True: time.sleep(0.5) except KeyboardInterrupt: observer.stop() observer.join() if __name__ == '__main__': argv = sys.argv[1:] if not argv: print('Usage: ./pymonitor your-script.py') exit(0) if argv[0] != 'python3': argv.insert(0, 'python3') command = argv path = os.path.abspath('.') start_watch(path, None)
用下面的命令啓動服務器,就能夠實現 Debug 模式的自動從新加載。瀏覽器
$ python3 pymonitor.py wsgiapp.py
或者給 pymonitor.py 加上可執行權限,啓動服務器:bash
$ ./pymonitor.py app.py
在編輯器中打開一個.py文件,修改後保存,看看命令行輸出,是否是自動重啓了服務器。這樣,就只要一保存代碼,就能夠刷新瀏覽器看到效果,大大提高了開發效率。服務器
在Web App框架和基本流程跑通後,剩下的工做就是在Debug開發模式下完成後端全部API、前端全部頁面。
首先,須要把當前用戶綁定到 request 上,並對 URL/manage/ 進行攔截,檢查當前用戶是不是管理員身份:
@asyncio.coroutine def auth_factory(app, handler): @asyncio.coroutine def auth(request): logging.info('check user: %s %s' % (request.method, request.path)) request.__user__ = None cookie_str = request.cookies.get(COOKIE_NAME) if cookie_str: user = yield from cookie2user(cookie_str) if user: logging.info('set current user: %s' % user.email) request.__user__ = user if request.path.startswith('/manage/') and (request.__user__ is None or not request.__user__.admin): return web.HTTPFound('/signin') return (yield from handler(request)) return auth
後端API包括:
獲取日誌:GET /api/blogs
建立日誌:POST /api/blogs
修改日誌:POST /api/blogs/:blog_id
刪除日誌:POST /api/blogs/:blog_id/delete
獲取評論:GET /api/comments
建立評論:POST /api/blogs/:blog_id/comments
刪除評論:POST /api/comments/:comment_id/delete
建立新用戶:POST /api/users
獲取用戶:GET /api/users
管理頁面包括:
評論列表頁:GET /manage/comments
日誌列表頁:GET /manage/blogs
建立日誌頁:GET /manage/blogs/create
修改日誌頁:GET /manage/blogs/
用戶列表頁:GET /manage/users
用戶瀏覽頁面包括:
註冊頁:GET /register
登陸頁:GET /signin
註銷頁:GET /signout
首頁:GET /
日誌詳情頁:GET /blog/:blog_id
把全部的功能實現,一個基本的 Web App 就此完成!
本文爲博主原創文章,轉載請註明出處!