<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          flask-siwadoc:一個(gè)自動(dòng)生成openapi接口文檔的庫(kù)

          共 4642字,需瀏覽 10分鐘

           ·

          2022-06-09 03:22


          在前后端分離變得越來(lái)越流行的今天,大家的職責(zé)也更加明確與專注,后端負(fù)責(zé)提供API接口,前端負(fù)責(zé)UI與交互。前后端基于接口文檔進(jìn)行溝通。

          但是程序員最討厭兩件事,一是討厭自己寫文檔,另一件是討厭別人不寫文檔。

          所以對(duì)后端來(lái)說(shuō),理想情況是代碼寫完,文檔已經(jīng)自動(dòng)生成好了。openapi(就是早前的swagger)已成為事實(shí)上的接口文檔規(guī)范指南,既然都有規(guī)范出現(xiàn),那么基于這份規(guī)范來(lái)實(shí)現(xiàn)一個(gè)自動(dòng)生成的openapi的接口文檔庫(kù)就不是難事了。

          所以我就寫了這樣一個(gè)庫(kù)

          名字叫flask-siwadoc ,它是一個(gè)兼具 數(shù)據(jù)校驗(yàn)和openapi(swagger)文檔自動(dòng)生成的項(xiàng)目。這兩個(gè)特性都是寫restful接口剛需痛點(diǎn)功能。

          現(xiàn)來(lái)說(shuō)說(shuō)這個(gè)庫(kù)的一些特點(diǎn):

          0、零配置

          接入flask-siwadoc無(wú)需任何配置, 只需要?jiǎng)?chuàng)建一個(gè)SiWaDoc實(shí)例,即可使用,沒有復(fù)雜的配置。當(dāng)然,在后面的版本,會(huì)開放相關(guān)的配置接口得以讓開發(fā)者根據(jù)自己的需求來(lái)配置openapi。

          1、數(shù)據(jù)校驗(yàn)

          flask-siwadoc 站在巨人肩膀上,數(shù)據(jù)校驗(yàn)利用pydantic強(qiáng)大的數(shù)據(jù)驗(yàn)證功能,支持請(qǐng)求查詢參數(shù)請(qǐng)求體參數(shù)的數(shù)據(jù)校驗(yàn)及轉(zhuǎn)換功能。因此本項(xiàng)目同時(shí)依賴于pydantic。

          2、接口文檔自動(dòng)生成

          接口文檔生成只需要簡(jiǎn)單初始化一個(gè)siwa=SiwaDoc(app),利用裝飾器 siwa.doc()修飾flask的視圖函數(shù),即可將該視圖函數(shù)加入openapi的接口文檔規(guī)范中。

          3、ui切換

          flask-siwadoc內(nèi)置了redocswaggerrapidoc等多種UI界面,通過(guò)參數(shù)/docs/?ui=xxx切換

          4、文檔支持分組與標(biāo)簽

          對(duì)于大型項(xiàng)目,接口分組和標(biāo)簽顯得尤為重要,不然前端很難找到相關(guān)接口。

          快速開始

          安裝

          pip?install?flask-siwadoc

          現(xiàn)在來(lái)看個(gè)簡(jiǎn)單例子:

          example 1

          初始化SiwaDoc支持兩種方式,一種直接將Flask實(shí)例傳入SiwaDoc的構(gòu)造方法,另一種是使用工廠模式進(jìn)行初始化。

          from?flask?import?Flask
          from?flask_siwadoc?import?SiwaDoc

          app?=?Flask(__name__)

          siwa?=?SiwaDoc(app)


          #?or
          #?siwa?=?SiwaDoc()
          #?siwa.init_app(app)

          @app.route("/hello",?methods=["GET"])
          @siwa.doc()
          def?hello():
          ????return?"hello?siwadoc"


          if?__name__?==?'__main__':
          ????app.run()

          運(yùn)行后,訪問(wèn) http://127.0.0.1:5000/docs 就可以看到該接口的文檔頁(yè)面


          對(duì)于大部分接口來(lái)說(shuō),我們要對(duì)請(qǐng)求參數(shù)進(jìn)行校驗(yàn),有的參數(shù)來(lái)源于url的查詢參數(shù),有的是以application/json格式作為請(qǐng)求體的參數(shù)。我們只需要基于Pydantic定義好對(duì)應(yīng)的Model數(shù)據(jù)結(jié)構(gòu),該結(jié)構(gòu)一方面可以用來(lái)做數(shù)據(jù)校驗(yàn),另一方面可用于生成openapi所需的schema。

          example 2:指定查詢參數(shù) query

          from?pydantic?import?BaseModel,?Field


          class?QueryModel(BaseModel):
          ????page:?int?=?Field(default=1,?title="current?page?number")
          ????size:?int?=?Field(default=20,?title="size?of?page",?ge=10,?le=100)


          @app.route("/users",?methods=["GET"])
          @siwa.doc(query=QueryModel,?tags=['user'])
          def?users_list():
          ????"""
          ????user?list
          ????"""

          ????return?[{"username":?"siwa",?"id":?1}]

          對(duì)于查詢接口,GET請(qǐng)求需如果有查詢參數(shù),得益于pydantic強(qiáng)大的類型功能,我們只需要一個(gè)繼承BaseModel的自定義類,即可實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)及轉(zhuǎn)換。

          如何在視圖函數(shù)中使用該query這個(gè)對(duì)象呢?有兩種方式

          方式一:

          @app.route("/users",?methods=["GET"])
          @siwa.doc(query=QueryModel,?tags=["user"])
          def?hello():
          ????print(request.query.keyword)
          ????return?"hello"

          flask-siwadoc 將QueryModel的實(shí)例對(duì)象query綁定到了flask的request對(duì)象上,不過(guò)對(duì)開發(fā)者來(lái)說(shuō)使用并不友好,從代碼上你沒法知道他是什么類型么,IDE也無(wú)法用.的方式調(diào)出該實(shí)例的屬性。你只有看了flask-siwadoc的文檔或者源碼才知道是怎么回事。

          方式二:(推薦方式)

          @app.route("/users",?methods=["GET"])
          @siwa.doc(query=QueryModel,?tags=["user"])
          def?hello(query:?QueryModel):
          ????print(query.keyword)
          ????return?"hello"

          query變量作為視圖函數(shù)的參數(shù),flask-siwadoc 會(huì)自動(dòng)將QueryModel實(shí)例對(duì)象注入到該函數(shù)一個(gè)叫query的變量中,我們可以給query指定類型聲明,因此通過(guò)IDE可以很方便的調(diào)出實(shí)例屬性。開發(fā)者一眼也能看出他的類型。

          下面的example3中的body參數(shù)原理也是類似的。


          example3 :指定請(qǐng)求體 body

          class?LoginModel(BaseModel):
          ????username:?str
          ????password:?str


          @app.route("/login",?methods=["POST"])
          @siwa.doc(body=LoginModel)
          def?login(body:?LoginModel):
          ????return?{"username":?body.username,?"id":?1}

          對(duì)于POST請(qǐng)求,請(qǐng)求體一般是基于application/json 類型, flask-siwadoc會(huì)自動(dòng)將數(shù)據(jù)轉(zhuǎn)換成LoginModel類型的對(duì)象,就可以像靜態(tài)語(yǔ)言一樣,通過(guò)點(diǎn)的方式調(diào)出屬性,例如 body.username


          example4: 指定返回體 resp

          對(duì)于接口文檔來(lái)說(shuō),除了要告訴前端需要傳什么參數(shù)之外,還需要告訴他們返回的結(jié)構(gòu)是什么,同樣也只需要定義一個(gè)Model,寫明有什么字段,字段對(duì)應(yīng)的類型是什么即可。在doc裝飾器中賦值給resp變量。

          class?UserModel(BaseModel):
          ????id:?int
          ????username:?str


          @app.route("/users/1",?methods=["GET"])
          @siwa.doc(resp=UserModel)
          def?users():
          ????"""
          ????user?detail
          ????"""

          ????return?{"username":?"siwa",?"id":?1}

          example5: 指定標(biāo)簽分類 tags

          項(xiàng)目中如果接口太多,我們可以對(duì)接口根據(jù)業(yè)務(wù)劃分不同的模塊標(biāo)簽來(lái)分類管理,我們只需要在裝飾器 siwa.doc 指定tags參數(shù)

          @siwa.doc(resp=UserModel,?tags=["user"])
          ...

          指定tags參數(shù),tags參數(shù)是一個(gè)列表,一個(gè)接口可支持多個(gè)標(biāo)簽。


          example6:路徑參數(shù)也支持文檔化

          除了查詢參數(shù)和請(qǐng)求體參數(shù)外,對(duì)于url路徑中的參數(shù),例如/users/,這是flask的路由語(yǔ)法,指users后面是一個(gè)必須大于1的整數(shù),生成文檔時(shí),不需要開發(fā)者做額外的處理,flask-siwadoc內(nèi)部經(jīng)過(guò)處理,直接將參數(shù)反映在接口文檔中。

          class?QueryModel(BaseModel):
          ????gender:?str


          class?UpdatePasswordModel(BaseModel):
          ????password:?str


          @app.route("/users/",?methods=["POST"])
          @siwa.doc(query=QueryModel,?body=UpdatePasswordModel,?resp=UserModel)
          def?update_password(user_id):
          ????"""
          ????update?password
          ????"""

          ????return?{"username":?"siwa",?"id":?user_id}

          完整示例可參考example.py

          UI切換

          文檔默認(rèn)使用redoc進(jìn)行渲染,你可以通過(guò)指定參數(shù)ui=swaggerui顯式文檔。

          http:?//?127.0
          .0
          .1:?5000?/?docs?/?ui?=?swagger

          擴(kuò)展

          如果數(shù)據(jù)校驗(yàn)報(bào)錯(cuò),flask-siwadoc 會(huì)拋出異常flask_siwadoc.error.ValidationErrorValidationError異常繼承自pydantic.ValidationError

          例如:


          class?QueryModel(BaseModel):
          ????keyword:?str


          @app.route("/users",?methods=["GET"])
          @siwa.doc(query=QueryModel,?tags=["user"])
          def?hello(query:?QueryModel):
          ????print(query)
          ????return?"hello"

          該接口中,keyword是必選的查詢參數(shù),如果url中沒有keyword參數(shù),就會(huì)拋出異常

          ????raise?ValidationError(e)
          flask_siwadoc.error.ValidationError:?2?validation?errors?for?Auth
          ????username
          field?required?(type=value_error.missing)
          password
          field?required?(type=value_error.missing)

          這時(shí)候,我們可以通過(guò)使用flask的 errorhandler() 裝飾函數(shù)來(lái)注冊(cè)ValidationError錯(cuò)誤,異常就可以被validate_error函數(shù)捕獲,開發(fā)者可以給前端直接返回一個(gè)友好的錯(cuò)誤響應(yīng)體

          @app.errorhandler(ValidationError)
          def?validate_error(e:?ValidationError):
          ????return?dict(code=-1,?msg="請(qǐng)求參數(shù)錯(cuò)誤",?error_info=e.errors()),?400

          github地址:https://github.com/lzjun567/flask-siwadoc

          任何問(wèn)題歡迎發(fā)issue或者加我微信 lzjun567 交流,歡迎PR

          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色二区| 欧美成人7601AV在线观看 | 久操香蕉| 九九九九精品视频 | www.久久6 |