最清洁的方式将生成的Flask应用程序代码(Swagger-Codegen)粘贴到后端实现 [英] cleanest way to glue generated Flask app code (Swagger-Codegen) to backend implementation
问题描述
我有:
- 一个函式库[Stuff]
- 一个swagger API定义,它大致排列第一,只有很小的差别,可以干净地映射到REST服务上。使用Swagger-Codegen生成第二个应用程序的烧瓶应用程序 - 例如python控制器函数大致是一对一的#1。
我的意图是烧瓶应用程序(所有生成的代码)应该只处理映射实际的REST API和参数解析以匹配在swagger编码的API规范。在任何参数解析(再次,生成的代码)之后,它应该直接调用我的(非生成)后端。
我的问题是,如何最好的钩住这些,而不用手工编辑生成的python / flask代码? (关于我的设计的反馈,或者正式设计模式的细节,也是非常棒的;我是新来的)
我最终得到了像python这样的函数:
pre $ def create_task(myTaskDefinition):
comment在swagger.json中指定
:param myTaskDefinition:json等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等。 .request.is_json:
myTaskDefinition = MyTaskTypeFromSwagger.from_dict(connexion.request.get_json())
return'do some magic!'#swagger codegen inserts this string :)
$ c
$ b在后端,我有我的实际逻辑:
def create_task_backend(myTaskDefinition):
#手动编码,检入git:执行所有的操作
返回APIResponse(...)
获取
create_tas的正确方法是什么k()
来调用create_task_backend()
?
当然,如果我对swagger规范做出重大修改,我将不得不手动更新非生成的代码;然而有很多原因,我可能想要重新生成我的API(例如,添加/精炼
MyTaskTypeFromSwagger
类,或跳过检查到git生成的代码),如果我必须手动编辑生成的API代码,然后所有这些编辑都会被重新生成。
当然,我可以用一个简单的语法在例如。 pyparsing;但是,虽然这是我第一次与这个问题,它似乎已被广泛解决已经!
解决方案以下方法适用于我:
-
创建了三个目录:
-
src-gen
对于我的代码,招摇的生成代码,
-
codegen
,其中我已经把脚本生成服务器以及一些技巧。 >
-
我将所有的模板(在swagger构建中可用)复制到
codegen / templates $ c $编辑
controller.mustache
来引用src / server_impl
,所以它可以使用我自己的代码。编辑使用模板语言,因此是通用的。尽管如此,它并不是完美的(我会改变一些命名约定),但是它完成了这项工作。因此,首先添加到controller.mustache
:
$ bfrom {packageName}}。server_impl.controllers_impl import {{classname}} _ impl
然后添加而不是
return'做一些魔术!'
如下:
< pre class =lang-mustache prettyprint-override>return {{classname}} _ impl。{{operationId}}({{allParams}} {{paramName}} {{^ ^ required}} =无{{/ required}},{{hasMore}} {{/ allParams}})
- 脚本:
-
src
server_impl
目录 - 创建一个symobolic链接,使得
server_impl
作为python模块导入
-
cd ../src-gen/swagger_server/
ln -s ../../src/server_impl/
cd ../../codegen
java -jar swagger-codegen-cli.jar生成\
-i / path_to_your_swagger definition.yaml \
-l python-flask \
-o ../src-gen \
-t ./templates
cd ../src-gen/
python3 -m swagger_server
I have:
- a library that does [Stuff]
- a swagger API definition, which is roughly #1 with minor differences to map cleanly to a REST service
- a flask app generated #2 using Swagger-Codegen - eg results in python controller functions roughly one-to-one with #1.
My intent is that the flask app (all generated code) should only handle mapping that actual REST api and parameter parsing to match the API spec coded in swagger. After any parameter parsing (again, generated code) it should call directly over to my (non-generated) backend.
My question is, how best to hook these up withOUT hand-editing the generated python/flask code? (Feedback on my design, or details of a formal design pattern that accomplishes this would be great too; I'm new to this space).
Fresh from the generator, I end up with python functions like:
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 :)
On the backend I have my actual logic:
def create_task_backend(myTaskDefinition): # hand-coded, checked into git: do all the things return APIResponse(...)
What is the right way to get
create_task()
to callcreate_task_backend()
?Of course if I make breaking changes to my swagger spec I will have to hand-update the non-generated code regardless; however there are many reasons I may want to re-generate my API (say, add/refine the
MyTaskTypeFromSwagger
class, or skip checking into git the generated code at all) and if I have to hand-edit the generated API code, then all those edits are blown away with each re-generation.Of course I could script this with a ~simple grammar in eg. pyparsing; but while this is my first time with this issue, it seems likely it's been widely solved already!
解决方案The following approach worked for me:
created three directories:
src
- for my code,src-gen
for the swagger generated code,codegen
in which I have put a script that generate the server along with a few tricks.
I copied all the templates (available in the swagger build) to
codegen/templates
and edited thecontroller.mustache
to refer tosrc/server_impl
, so it can use my own code. The editing uses the template language so it is generic. Still it is not perfect (I would change a few naming conventions) but it does the job. So, first add tocontroller.mustache
:
from {packageName}}.server_impl.controllers_impl import {{classname}}_impl
then add instead of
return 'do some magic!'
the following:return {{classname}}_impl.{{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
- Script:
- The
src
has aserver_impl
directory. - It creates a symobolic link so that
server_impl
can be imported as a python module
- The
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
这篇关于最清洁的方式将生成的Flask应用程序代码(Swagger-Codegen)粘贴到后端实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 脚本:
-