摘要:另外一個則用于健康檢查。聯(lián)合使用這些查詢條件可以看到僅僅返回了中列出的列而且按照過濾的結(jié)果并且根據(jù)中的排序條件進行了排序。數(shù)據(jù)庫中沒有記錄的以及沒有關(guān)聯(lián)的是對所有人開放的。
一、系統(tǒng)和環(huán)境要求tadpole 是一個flask starter 項目。從平時flask項目的開發(fā)過程中提出來的一些通用的功能,如通過gunicorn管理flask應(yīng)用的配置文件和啟動腳本,初始化virtualenv環(huán)境同時安裝必要的依賴庫,生成flask secret以及提供restful route, 自動為sqlalchey model注冊restful接口, 登錄認證,權(quán)限管理, restful支持等等技能。
posix, Python 2.x >= 2.6
二、 安裝方法pip install tadpole
三、git地址https://github.com/echoyuanliang/tadpole
歡迎pull request, 一起做好這個項目, 如果覺得不錯, 歡迎star。
四、 使用方法tadpole init -n PROJECT_NAME -v PROJECT_VERSION -o PROJECT_OWNER -e PROJECT_EMAIL
其中PROJECT_NAME是初始化的項目名,PROJECT_VERSION是初始化的版本號(默認為0.0.1), PROJECT_OWNER為項目負責人,
PROJECT_EMAIL為項目郵件組(用于接收郵件)。
也可以直接執(zhí)行tadpole init 會提示填入項目名,其他采用默認, 例如:
五、項目結(jié)構(gòu)至此,已經(jīng)使用tadpole初始化了一個新的flask項目,進入tadpole-demo目錄可以看到
requirements.txt 新項目依賴第三方庫列表(其中包含了flask項目常用依賴庫)
venv 為新項目生成的virtualenv 環(huán)境,其中已經(jīng)安裝了requirements.txt中聲明的依賴項
main.py 項目入口文件,其中定義了Flask app
app 主要代碼目錄
config.py 配置文件(會上傳git,主要包含不涉秘配置項)
instance 其中由instance/config.py, 本地配置項,已經(jīng)加入.gitignore, 不會上傳git,其中為涉密配置或本地特殊配置,其中配置可以覆蓋config.py中配置
gun.py gunicorn配置文件
data 項目數(shù)據(jù)目錄,已經(jīng)加入.gitignore
logs 項目日志目錄,已經(jīng)加入.gitignore
dev 本地調(diào)試管理腳本,由于具有項目的所有權(quán)限,因此已經(jīng)加入.gitignore,僅供本地調(diào)試
tadpole-demo 以項目名gunicorn管理腳本,提供了gunicorn啟動/停止/重新加載等技能
六、管理腳本的使用 6.1 dev的使用dev是提供給開發(fā)者在開發(fā)環(huán)境下使用的工具,其中提供了如下技能
create_db: 根據(jù)model自動生成表結(jié)構(gòu)
url: 展示所有注冊url
clean: 刪除項目目錄下所有pyc,pyo文件
shell: 以命令行方式侵入應(yīng)用
runserver: 使用flask內(nèi)置的web服務(wù)器在5000端口啟動應(yīng)用
此處僅以 url 為例:
可以看到新初始化的項目已經(jīng)有這么多注冊的url了,其中prefix為/api/v0.0.1/rest_db開頭的url都是為已經(jīng)創(chuàng)建的
user,role,resource三張表自動生成的restful api。另外一個/health則用于健康檢查。最后的/static/則是flask默認提供的。
start 用gunicorn啟動flask應(yīng)用,如:
status 用于顯示gunicorn應(yīng)用狀態(tài),如:
stop 用于停止gunicorn應(yīng)用
reload 用于重新加載gunicorn配置文件,同時重新啟動worker進程(目前只支持linux,不支持mac)
七、提供的基本技能 7.1 sqlalchemy restful model工作中經(jīng)常會有人要接口查詢數(shù)據(jù),但是很多數(shù)據(jù)只需要執(zhí)行sql語句就能拿到數(shù)據(jù),但是又不能直接把DB權(quán)限給別人,
因此提供了一個把簡單sql語句自動對應(yīng)到restful查詢的技能。這個技能實際上市面上已經(jīng)有很多庫提供了,但是
并沒有遇到讓我自己用的很舒服的庫,因此自己寫了一個,這個技能之只需要用戶寫Model類,并直接或間接的
import到app/models/__init__.py中即可為其自動注冊restful接口。
為了初始化出來的項目可以開箱即用, 會給默認的db(sqlite數(shù)據(jù)庫,文件位于app.db)中創(chuàng)建user,role,resource等
表結(jié)構(gòu),同時會插入部分數(shù)據(jù),因此訪問已經(jīng)注冊的rest_db url是可以直接拿到數(shù)據(jù)的, 例如:
curl http://127.0.0.1:8080/api/v0.0.1/rest_db/user { "code": 200, "msg": "ok", "result": { "next_page": "http://127.0.0.1:8080/api/v0.0.1/rest_db/user?__page=2&__page_size=200", "page": 1, "page_size": 200, "prev_page": null, "result": [ { "__roles_link": "http://127.0.0.1:8080/api/v0.0.1/rest_db/user/1/roles", "account": "tadpole", "create_time": "2017-11-26 17:53:13", "email": "tadpole@tadpole.com", "id": 1, "name": "tadpole" } ] } }
可以看到user表已經(jīng)有一條記錄了,同時__roles_link鏈接到了每個用戶所擁有的角色,直接訪問可以看到
curl http://127.0.0.1:8080/api/v0.0.1/rest_db/user/1/roles { "msg": "ok", "code": 200, "result": { "next_page": "http://127.0.0.1:8080/api/v0.0.1/rest_db/user/1/roles?__page=2&__page_size=200", "prev_page": null, "result": [ { "description": "super admin", "__resources_link": "http://127.0.0.1:8080/api/v0.0.1/rest_db/role/1/resources", "__users_link": "http://127.0.0.1:8080/api/v0.0.1/rest_db/role/1/users", "create_time": "2017-11-26 17:42:52", "id": 1, "name": "root" } ], "page_size": 200, "page": 1 } }
可以看到tadpole這個用戶已經(jīng)擁有了一個root角色, 每一條記錄除了返回自己的的列之外還以__{relation}_link的形式返回了其關(guān)聯(lián)關(guān)系的鏈接。
7.1.1 支持的查詢條件OPERATORS = ("lt", "le", "gt", "ge", "eq", "like", "in", "between") PROCESSES = ("__show", "__order") PAGINATE = ("__page", "__page_size")
查詢條件分為3類,一類是基本的運算符在OPERATORS中,另一類是對查詢的數(shù)據(jù)進行一些處理,如排序、只展示部分列等,另一類則是分頁。
聯(lián)合使用這些查詢條件:
curl http://127.0.0.1:5000/api/v0.0.1/rest_db/user?name=tadpole&account.like=tad%&__show=account,email&__order=id.asc,name.desc { "msg": "ok", "code": 200, "result": { "next_page": "http://127.0.0.1:5000/api/v0.0.1/rest_db/user?name=tadpole&__page_size=200&__page=2&account.like=tad%25&__order=id.asc%2Cname.desc&__show=account%2Cemail", "prev_page": null, "result": Array[1][ { "account": "tadpole", "email": "tadpole@tadpole.com" } ], "page_size": 200, "page": 1 } }
可以看到僅僅返回了__show中列出的列,而且按照name=tadpole,account.like=tad%過濾的結(jié)果,并且根據(jù)__order中的排序條件進行了排序。
7.1.2 url規(guī)則可以看出生成的url都是有一定規(guī)則的, prefix為/api/v0.0.1,其中v0.0.1是項目的版本號,但是這個是可以定制的。通過配置文件中的BP_PREFIX就可以配置每一個bluprint對應(yīng)的prefix,例如rest_db這個blueprint(即rest model使用的)的配置可以如下:
BP_PREFIX = { "rest_db": "/api/{0}/rest_db/".format(VERSION) }
除了prefix之外,后面緊跟著的則是表名,如果是關(guān)聯(lián)查詢則是{prefix}/{table_name}/{pk_id}/{relation_name}
7.1.3 自動隱藏并不是所有的列都適合展示,有些列(比如密碼,并不適合對外開放),初始化出來的項目對user表的password列就做了隱藏,如下:
class User(Model): # columns in __hide__ does"nt show in rest_db __hide__ = ("password",) account = Column( db.String(128), nullable=False, default=u"-", index=True, unique=True) name = Column(db.String(32), nullable=False, default=u"-") email = Column(db.Email(128), nullable=False, default=u"-") password = Column(db.Password(schemes=["pbkdf2_sha512", "md5_crypt"], deprecated=["md5_crypt"]), nullable=False, default=u"-")
聲明Model時, __hide__元組中的列不會在自動生成的restful接口中展示
7.2 登錄控制和權(quán)限管理對于每一個應(yīng)用來說,都有不適合對所有人開放的資源,因此需要登錄控制和權(quán)限管理。tadpole默認在app/models/auth包中實現(xiàn)了用戶和權(quán)限依賴的Model,
在app/lib/auth.py中實現(xiàn)了有關(guān)登錄和權(quán)限驗證的邏輯。登錄驗證目前采用的是Http Basic認證, 因為密碼是單向加密存儲的,所以有些驗證方法(如Http Digest)不能直接使用,有需求可以對代碼進行擴展。擴展也十分容易,有興趣的朋友可以閱讀實現(xiàn)源碼進行擴展。權(quán)限校驗則是簡單的查詢數(shù)據(jù)庫看用戶有沒有對某一資源執(zhí)行某一操作的權(quán)限(此處也可以很容易擴展自己的校驗方式),權(quán)限校驗?zāi)J對restful接口的http method進行了支持,因此只需要在數(shù)據(jù)庫中添加合適的記錄既可以做到接口的權(quán)限控制。為了應(yīng)用可以開箱即用,已經(jīng)對/api/v0.0.1/rest_db/開頭的url做了權(quán)限限制,其POST,DELETE,PUT方法僅有root權(quán)限用戶可以操作,如:
對于新初始化的項目,已經(jīng)添加了account=tadpole-demo,password=12qwaszx的用戶,并且賦予了root角色,可以執(zhí)行POST /api/v0.0.1/rest_db/*測試權(quán)限校驗是否正確。
只需要把resource 和 role關(guān)聯(lián)起來即可以僅開放給對應(yīng)角色的用戶。數(shù)據(jù)庫中沒有記錄的resource以及沒有關(guān)聯(lián)role的resource是對所有人開放的。一個資源開放給的用戶是資源名稱可以正則匹配的到所有resource.name,且對資源的操作在resource.operation(用","分割)中的資源列表所開放給的角色所擁有的用戶。 例如對于http restful接口的權(quán)限校驗, 會拿出所有匹配path 和 method的resource,然后查詢這些resource開放的role列表,要求用戶只有滿足所有這些role,才可以訪問對應(yīng)接口。
7.3 關(guān)于rest_route對于restful接口來說, 一是參數(shù)的校驗幾乎都需要,二是希望可以返回python對象,由框架自動處理成json格式。rest_route對這些做了支持。
如:
from main import app validator = { "required": ["user_name"] } @app.rest_route("/welcome", methods=["GET"], validator=validator) def welcome(data): return "hell0", data["user_name"]
首先validator中可以對參數(shù)進行校驗,默認實現(xiàn)了幾種常用校驗,也可以自己擴充,除此之外還實現(xiàn)了custom校驗,即傳入用戶自己的校驗函數(shù),這段代碼提供了對user_name參數(shù)必填的校驗。除此之外,為了提供統(tǒng)一的提交數(shù)據(jù)入口,所有提交數(shù)據(jù)都被merge到data參數(shù)中了,rest_route接口的POST方法必須提交json格式數(shù)據(jù)。最后返回一個元組,在rest_route中會自動將其轉(zhuǎn)化為json list,請求這個接口返回如下:
curl http://127.0.0.1:5000/welcome { "msg": "param user_name is required", "code": 400 } curl http://127.0.0.1:5000/welcome?user_name=tadpole { "msg": "ok", "code": 200, "result": Array[2][ "hell0", "tadpole" ] }
返回結(jié)果不僅支持直接返回元組,還支持sqlalchemy查詢結(jié)果直接返回,set返回等等。對于用戶自定義的對象如果要支持直接返回,只需要實現(xiàn)to_dict/_as_dict方法將對象轉(zhuǎn)化成dict即可。
7.3.1 默認支持的參數(shù)校驗方式參數(shù)校驗是通過app/lib/validator實現(xiàn)的,有興趣的朋友可以直接看源碼,實現(xiàn)很簡單,也可以自己擴展。目前實現(xiàn)的校驗方式有以下:
required: 必填參數(shù)列表, 用戶必須填充但可以為空字符串. 數(shù)據(jù)類型為list
nonempty: 必填且不能為空參數(shù)列表。數(shù)據(jù)類型為list
types: 參數(shù)類型校驗, 數(shù)據(jù)類型為dict,例如:
validator = { "types": { "age": int, "active": bool, } }
oneof: 如果參數(shù)名稱位于oneof中,其值必須要屬于oneof[param_name]中的一個,數(shù)據(jù)類型為dict
unique: 對list類型參數(shù)做去重,數(shù)據(jù)類型為list
length: 對參數(shù)長度組校驗, 數(shù)據(jù)類型為dict
default: 對參數(shù)提供默認值, 數(shù)據(jù)類型為list
override: 用對參數(shù)處理后的結(jié)果取代參數(shù)的值,數(shù)據(jù)
custom: 用戶自定義校驗方法,數(shù)據(jù)類型為list
例如:
validator = { "required": ["task_id"], # 必填參數(shù) "nonempty": ["project", "env", "ip_list", "component"], # 不能為空 "types": { "ip_list": list, "mem": int }, "unique": ["ip_list"], # 對ip_list參數(shù)去重 "default": { "region": "Shanghai" # 如果用戶沒有填寫region參數(shù),則用Shanghai填充 }, "oneof": { "region": ["Shanghai", "Beijing"], # region參數(shù)必屬于Shanghai和Beijing之一 } }7.3.2 關(guān)于異常處理
已經(jīng)實現(xiàn)了異常的自動捕捉,并返回合適的信息,默認提供的異常在app/lib/exceptions.py中,
所有繼承自CustomError的異常都會被捕捉,并且返回msg作為錯誤信息,code作為返回碼,因此可以直接拋出這些異常給用戶,
不需要再進行處理。也可以擴展自定義的異常。默認異常定義示例:
class CustomError(Exception): def __init__(self, msg): super(CustomError, self).__init__(msg) self.msg = msg self.code = 500 def to_dict(self): return dict(code=self.code, msg=self.msg) def __unicode__(self): return unicode(self.msg) def __str__(self): return str(self.msg) class InternalError(CustomError): def __init__(self, msg): super(InternalError, self).__init__(msg) self.code = 500
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/44536.html
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 為什么會有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實現(xiàn)淺拷貝與深拷貝好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 以下↓ 數(shù)據(jù)類型在開始了解 淺拷貝 與 深拷貝 之前,讓我們先...
摘要:所以,深拷貝是對對象以及對象的所有子對象進行拷貝實現(xiàn)方式就是遞歸調(diào)用淺拷貝對于深拷貝的對象,改變源對象不會對得到的對象有影響。 上一篇 JavaScript中的繼承 前言 文章開始之前,讓我們先思考一下這幾個問題: 為什么會有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實現(xiàn)淺拷貝與深拷貝 好了,問題出來了,那么下面就讓我們帶著這幾個問題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯誤之處...
摘要:而在國內(nèi)確實用的人太少,國內(nèi)的主流服務(wù)端語言都被霸占。因此,在進行調(diào)研和諸多權(quán)衡后,團隊選擇了作為第二支持語言。整體上使用開發(fā),也用了一些的特性,之所以用,是因為對于項目的開發(fā)和維護有極大的益處。 初衷 lin-cms是我們林間有風團隊開源的一款CMS,它采用目前主流的前后端分離的架構(gòu),前端使用vue作為基礎(chǔ)框架,后端選擇了我們團隊大量實踐使用的flask作為基礎(chǔ)框架。 lin-cms...
摘要:推薦閱讀資源庫工具應(yīng)用程序精選列表中文版有哪些鮮為人知,但是很有意思的網(wǎng)站一份攻城獅筆記每天搜集上優(yōu)秀的項目一些有趣的民間故事超好用的谷歌瀏覽器油猴插件合集目錄資源文檔文章圖書會談教程更多庫工具管理數(shù)據(jù)部署桌面發(fā)展監(jiān)控應(yīng)用資源文檔介紹文檔教 推薦閱讀 MongoDB 資源、庫、工具、應(yīng)用程序精選列表中文版 有哪些鮮為人知,但是很有意思的網(wǎng)站? 一份攻城獅筆記 每天搜集 Github ...
摘要:如果設(shè)置為,命令將激活模式,執(zhí)行會啟用交互式調(diào)試器和代碼自動重載。也可以通過變量單獨控制,表示啟用,表示禁用通過設(shè)置環(huán)境變量略通過設(shè)置環(huán)境變量略自定義命令命令基于庫實現(xiàn)。 應(yīng)用發(fā)現(xiàn) flask命令在Flask庫安裝后可使用,使用前需要正確配置FLASK_APP環(huán)境變量以告知用戶程序所在位置。不同平臺設(shè)置方式有所不同。 Unix Bash (Linux, Mac, etc.): $ ex...
閱讀 2178·2023-04-25 19:06
閱讀 1375·2021-11-17 09:33
閱讀 1767·2019-08-30 15:53
閱讀 2582·2019-08-30 14:20
閱讀 3541·2019-08-29 12:58
閱讀 3534·2019-08-26 13:27
閱讀 501·2019-08-26 12:23
閱讀 485·2019-08-26 12:22