<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                在上一章中簡單的進行了在開發中經常要經過的一個步驟——詳細設計,在詳細設計中定義了數據模型,有哪些接口,以及頁面的長相。比較簡單,并沒有對服務器端Python項目的結構進行設計,也沒有對前端文件的組織進行規劃。但是這個詳細設計的目的是達到了,在我個人的實際經驗中,項目的開發很少有按照軟件工程中的瀑布模型來做的。大部分都是明確階段目標,然后開發,然后再次明確,再次開發,不斷迭代。 因此說到前篇文章的目的也就是指導后端開發提供一個什么樣的接口,輸出什么樣的數據結構。也是指導前端應該怎么獲取數據。在日常工作中,設計到前后端甚至是服務器和客戶端的這種模式也是一樣,兩方人員在項目初期只要協定好接口和數據結構就行,隨著項目的進行不斷的調整。當然這種情況是說內部人員之間的溝通,如果是和外部人員的溝通情況就不一樣了。 回到正題,后端的開發主要功能是提供接口,要提供哪些接口一定定義好了,模型也建立好了,現在需要做的就是搭一個項目,實現接口。 ## 13.1 項目結構 項目使用了webpy這個微型的python框架,項目結構是依然按照之前對todos進行服務器端擴展時的結構,?[onlinetodos](https://github.com/the5fire/onlinetodos) ~~~ . ├── __init__.py ├── handlers.py ├── init_sqlite.py ├── models.py ├── server.py ├── static │?? ├── css │?? │?? ├── body.css │?? │?? └── semantic.min.css │?? ├── img │?? │?? └── bg.jpg │?? └── js │?? ├── backbone.js │?? ├── jquery.js │?? ├── json2.js │?? └── underscore.js ├── templates │?? └── index.html └── wechat.db ~~~ 可以先忽略其中的靜態文件的部分,下一章實現的時候會進行調整。只說后端的實現,主要分為三個部分:server部分、handler部分、和models部分,也就是上面對應的名字,這些名字本身就說明了這部分的功能。server主要是啟動一個web服務器,其中進行了url的定義,對應url接受到的請求會傳遞到handlers中對應的類方法中,在方法中會調用Models中的Model類來獲取數據,然后再返回給客戶端(瀏覽器)。 ## 13.2 server部分詳解 這部分功能上已經介紹了,這里貼出代碼詳細介紹: ~~~ #!/usr/bin/env python #coding:utf-8 import web from web.httpserver import StaticMiddleware urls = ( '/', 'IndexHandler', # 返回首頁 '/topic', 'TopicHandler', '/topic/(\d+)', 'TopicHandler', '/message', 'MessageHandler', '/user', 'UserHandler', '/user/(\d+)', 'UserHandler', '/login', 'LoginHandler', '/logout', 'LogoutHandler', ) app = web.application(urls, globals()) application = app.wsgifunc(StaticMiddleware) if web.config.get('_session') is None: session = web.session.Session( app, web.session.DiskStore('sessions'), initializer={'login': False, 'user': None} ) web.config._session = session from handlers import ( # NOQA IndexHandler, RegisteHandler, LoginHandler, LogoutHandler, TopicHandler, MessageHandler ) def main(): app.run() if __name__ == "__main__": main() ~~~ 這里首先是定義了url對應的handlers中的類,然后通過webpy的靜態文件Middleware來處理靜態文件的請求,接著初始化了項目的session。最后從handlers中引入所有用到的Handler。這里需要注意的是,handlers的引入需要在session定義的下面,因為handlers中需要用到session。 ## 13.3 handler中的邏輯 這里面主要邏輯是處理來自瀏覽器對相應的url的請求,因為項目需要處理用戶登錄,因此要引入前面定義的session來保存用戶的狀態。 來看代碼: ~~~ #coding:utf-8 import copy import json import hashlib import sqlite3 from datetime import datetime import web from models import Message, User, Topic session = web.config._session CACHE_USER = {} def sha1(data): return hashlib.sha1(data).hexdigest() def bad_request(message): raise web.BadRequest(message=message) # 首頁 class IndexHandler: def GET(self): render = web.template.render('templates/') return render.index() class UserHandler: def GET(self): # 獲取當前登錄的用戶數據 user = session.user return json.dumps(user) def POST(self): data = web.data() data = json.loads(data) username = data.get("username") password = data.get("password") password_repeat = data.get("password_repeat") if password != password_repeat: return bad_request('兩次密碼輸入不一致') user_data = { "username": username, "password": sha1(password), "registed_time": datetime.now(), } try: user_id = User.create(**user_data) except sqlite3.IntegrityError: return bad_request('用戶名已存在!') user = User.get_by_id(user_id) session.login = True session.user = user result = { 'id': user_id, 'username': username, } return json.dumps(result) class LoginHandler: def POST(self): data = web.data() data = json.loads(data) username = data.get("username") password = data.get("password") user = User.get_by_username_password( username=username, password=sha1(password) ) if not user: return bad_request('用戶名或密碼錯誤!') session.login = True session.user = user result = { 'id': user.get('id'), 'username': user.get('username'), } return json.dumps(result) class LogoutHandler: def GET(self): session.login = False session.user = None session.kill() return web.tempredirect('/#login') class TopicHandler: def GET(self, pk=None): if pk: topic = Topic.get_by_id(pk) return json.dumps(topic) topics = Topic.get_all() result = [] for t in topics: topic = dict(t) try: user = CACHE_USER[t.owner_id] except KeyError: user = User.get_by_id(t.owner_id) CACHE_USER[t.owner_id] = user topic['owner_name'] = user.username result.append(topic) return json.dumps(result) def POST(self): if not session.user or not session.user.id: return bad_request('請先登錄!') data = web.data() data = json.loads(data) topic_data = { "title": data.get('title'), "owner_id": session.user.id, "created_time": datetime.now(), } try: topic_id = Topic.create(**topic_data) except sqlite3.IntegrityError: return bad_request('你已創建過該名稱!') result = { "id": topic_id, "title": topic_data.get('title'), "owner_id": session.user.id, "owner_name": session.user.username, "created_time": str(topic_data.get('created_time')), } return json.dumps(result) def PUT(self, obj_id=None): pass def DELETE(self, obj_id=None): pass class MessageHandler: def GET(self): topic_id = web.input().get('topic_id') if topic_id: messages = Message.get_by_topic(topic_id) or [] else: messages = Message.get_all() result = [] current_user_id = session.user.id for m in messages: try: user = CACHE_USER[m.user_id] except KeyError: user = User.get_by_id(m.user_id) CACHE_USER[m.user_id] = user message = dict(m) message['user_name'] = user.username message['is_mine'] = (current_user_id == user.id) result.append(message) return json.dumps(result) def POST(self): data = web.data() data = json.loads(data) if not (session.user and session.user.id): return bad_request("請先登錄!") message_data = { "content": data.get("content"), "topic_id": data.get("topic_id"), "user_id": session.user.id, "created_time": datetime.now(), } m_id = Message.create(**message_data) result = { "id": m_id, "content": message_data.get("content"), "topic_id": message_data.get("topic_id"), "user_id": session.user.id, "user_name": session.user.username, "created_time": str(message_data.get("created_time")), "is_mine": True, } return json.dumps(result) ~~~ 別看代碼這么多,所有的具體的Handler的處理邏輯都是一樣的——接受post請求,驗證用戶狀態,存儲;或者是接受get請求,調用Model獲取數據,組織成json,然后返回。相當簡單了,對吧。 ## 13.4 models中的實現 這部分功能就是現實數據庫的增刪改查,行為基本一致,因此提出一個基礎類來完成基本的操作。如果基礎類滿足不了需求,需要在各子類中實現自己的邏輯。 來看下實現代碼: ~~~ #coding:utf-8 import web db = web.database(dbn='sqlite', db="wechat.db") class DBManage(object): @classmethod def table(cls): return cls.__name__.lower() @classmethod def get_by_id(cls, id): itertodo = db.select(cls.table(), where="id=$id", vars=locals()) return next(iter(itertodo), None) @classmethod def get_all(cls): # inspect.ismethod(cls.get_all) return db.select(cls.table()) @classmethod def create(cls, **kwargs): return db.insert(cls.table(), **kwargs) @classmethod def update(cls, **kwargs): db.update(cls.table(), where="id=$id", vars={"id": kwargs.pop('id')}, **kwargs) @classmethod def delete(cls, id): db.delete(cls.table(), where="id=$id", vars=locals()) class User(DBManage): id = None username = None password = None registed_time = None @classmethod def get_by_username_password(cls, username, password): itertodo = db.select(cls.table(), where="username=$username and password=$password", vars=locals()) return next(iter(itertodo), None) class Topic(DBManage): id = None title = None created_time = None owner = None class Message(DBManage): id = None content = None top_id = None user_id = None reply_to = None @classmethod def get_by_topic(cls, topic_id): return db.select(cls.table(), where="topic_id=$topic_id", vars=locals()) ~~~ 在操作的同時還是定義了模型的屬性,不過目前并沒有用的上,如果打算進一步抽象的話是要用到的。 ## 13.5 總結 整個后端的實現并不復雜,只是簡單的數據庫CRUD操作,也沒有進行更深一步的抽象,不過滿足接口需求就好,等前端實現的時候可能需要調整。 這個項目已經托管在github上了:?[wechat](https://github.com/the5fire/wechat)?,歡迎圍觀以及貢獻代碼。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看