[英]cleanest way to glue generated Flask app code (Swagger-Codegen) to backend implementation
我有:
我的意圖是,flask應用程序(所有生成的代碼)應僅處理實際REST api和參數解析的映射,以匹配以大方的方式編碼的API規范。 在解析完任何參數(再次生成的代碼)之后,它應該直接調用我的(非生成的)后端。
我的問題是,如何最好地不手工編輯生成的python / flask代碼? (反饋我的設計,或完成此工作的正式設計模式的細節也很棒;我是這個領域的新手)。
從生成器開始,我最終得到了python函數,例如:
def create_task(myTaskDefinition):
"""
comment as specified in swagger.json
:param myTaskDefinition: json blah blah blah
:type myTaskDefinition: dict | bytes
:rtype: ApiResponse
"""
if connexion.request.is_json:
myTaskDefinition = MyTaskTypeFromSwagger.from_dict(connexion.request.get_json())
return 'do some magic!' # swagger codegen inserts this string :)
在后端,我有實際的邏輯:
def create_task_backend(myTaskDefinition):
# hand-coded, checked into git: do all the things
return APIResponse(...)
什么是使create_task()
調用create_task_backend()
的正確方法?
當然,如果我對搖搖欲墜的規格進行了重大更改,則無論如何我都必須手動更新未生成的代碼。 但是,出於多種原因,我可能想重新生成我的API(例如,添加/優化MyTaskTypeFromSwagger
類,或者完全跳過git生成的代碼),如果我必須手動編輯生成的API代碼,則所有每次重新生成時,這些編輯都會被刪除。
當然,我可以使用例如〜的簡單語法編寫腳本。 剖析 但是,盡管這是我第一次遇到此問題,但似乎已經被廣泛解決了!
以下方法對我有用:
創建了三個目錄:
src
對於我的代碼, src-gen
生成的代碼 codegen
中,我已經把那有幾個竅門生成服務器的腳本。 我將所有模板(可在swagger構建中使用)復制到codegen/templates
並編輯controller.mustache
以引用src/server_impl
,因此它可以使用我自己的代碼。 編輯使用模板語言,因此它是通用的。 它仍然不是完美的(我會更改一些命名約定),但是確實可以。 因此,首先添加到controller.mustache
:
from {{packageName}}.server_impl.controllers_impl import {{classname}}_impl
然后添加而不是return 'do some magic!'
下列:
return {{classname}}_impl.{{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
src
有一個server_impl
目錄。 server_impl
可以作為python模塊導入 cd ../src-gen/swagger_server/
ln -s ../../src/server_impl/
cd ../../codegen
java -jar swagger-codegen-cli.jar generate \
-i /path_to_your_swagger definition.yaml \
-l python-flask \
-o ../src-gen \
-t ./templates
cd ../src-gen/
python3 -m swagger_server
以前我很想使用swagger-codegen
並遇到相同的難題。 一切正常,直到您更新規格。 盡管您可以使用自定義模板,但是當我想要的只是設計優先的API時,這似乎需要大量的開銷和維護。
我最終使用了connexion ,它使用了swagger規范來自動處理路由,封送處理,驗證等。Connexion構建在flask上,因此您不必擔心切換框架或其他任何事情,您將獲得部分收益可以自動處理所有應用程序,而不必維護自動生成的代碼。
現在,我正在按以下步驟進行構建,以解決此問題
'do some magic'
(即所有生成的控制器端點返回的字符串),而只需在我的“后端”中調用相應的函數 git format-patch
對先前的更改進行修補,以便在我重新生成代碼時,構建可以自動應用更改。 因此,我可以添加新的端點,並且只需要手動將調用編碼到后端即可。 無需使用補丁文件,我可以直接通過為生成的代碼編寫py解析語法並使用解析的生成的代碼來創建對我的后端的調用來直接執行此操作……這將花費更長的時間,因此我很快就做了所有這些駭客。
這遠非最佳,我不會將其標記為已接受,因為我希望有人會提供真正的解決方案。
我參加的工作流程。
這個想法是生成代碼,然后將swagger_server
包解壓縮到項目目錄。 但是要分開使用,將您正在編寫的控制器保留在單獨的目錄中,或者(如我所做的那樣)在項目根目錄中,並在每代之后使用git merge-files
將它們與生成的控制器git merge-files
。 然后,您需要將新的控制器代碼注入swagger_server/controllers
,即在啟動服務器之前。
project
+-- swagger_server
| +-- controllers
| +-- controller.py <- this is generated
+-- controller.py <- this is you are typing your code in
+-- controller.py.common <- common ancestor, see below
+-- server.py <- your server code, if any
因此,工作流程如下:
swagger_server
復制到您的項目目錄,完全覆蓋現有文件 controller.py
和controller.py.common
git merge-file controller.py controller.py.common swagger_server/controllers/controller.py
swagger_server/controllers/controller.py
設為新的共同祖先,然后將其復制到controller.py.common
,覆蓋現有的 隨意使用shell腳本自動化所有這些操作,即
#!/bin/bash
# Swagger generate server and client stub based on specification, them merge it into the project.
# Use carefully! Commit always before using this script!
# The following structure is assumed:
# .
# +-- my_client
# | +-- swagger_client
# +-- my_server
# | +-- swagger_server
# +-- merge.sh <- this script
read -p "Have you commited the project??? " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo 'Commit first!'; exit 1; fi
rm -rf swagger-python-client
rm -rf swagger-python-server
java -jar swagger-codegen-cli.jar generate -i swagger.yaml -l python -o swagger-python-client
java -jar swagger-codegen-cli.jar generate -i swagger.yaml -l python-flask -o swagger-python-server
# Client - it's easy, just replace swagger_client package
rm -rf my_client/swagger_client
cp -rf swagger-python-client/swagger_client/ my_client
# Server - replace swagger_server package and merge with controllers
rm -rf my_server/.backup
mkdir -p my_server/.backup
cp -rf my_server/swagger_server my_server/.backup
rm -rf my_server/swagger_server
cp -rf swagger-python-server/swagger_server my_server
cd my_server/swagger_server/controllers/
files=$( ls * )
cd ../../..
for f in $files; do
# skip __init__.py
if [ -z "$flag" ]; then flag=1; continue; fi
echo "======== $f"
# initialization
cp -n my_server/swagger_server/controllers/$f my_server/$f.common
cp -n my_server/swagger_server/controllers/$f my_server/$f
# real merge
cp -f my_server/$f my_server/.backup/
cp -f my_server/$f.common my_server/.backup/
git merge-file my_server/$f my_server/$f.common my_server/swagger_server/controllers/$f
cp -f my_server/swagger_server/controllers/$f otmini-repo/$f.common
done
rm -rf swagger-python-client
rm -rf swagger-python-server
建議使用connexion作為@MrName。
我首先開始將其與Codegen一起使用。
openapi-generator generate -i ../myapi.yaml -g python-flask -o .
這將使用openapi服務器生成目錄。
|- openapi_server\
|--controllers\
|--mytag._controller.py\
|--openapi\
|--my-api.yaml\
如果您將標簽添加到api規范中的路徑中,則會為每個標簽創建一個單獨的tagname-controller.py。 對於每個operationId,都會生成一個函數。
但是,一旦設置完成,connexion就可以處理對api規范的更新。 如果我使用operationId = new_func將新路徑添加到openapi / my-api.yaml,則可以將new_func()添加到現有控制器。 我不會丟失現有的服務器邏輯(但是為了以防萬一,我還是會備份它)。 我還沒有嘗試對現有路徑進行重大更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.