如何加快 python 中 rest api 的开发速度?
How to speed up development of rest api in python?
我正在尝试使用 FastApi 和 sqlAchemy 创建后端应用程序。我有很多与数据库有关系的实体。所以,我的问题是:如何加快发展?现在我为每个实体代码编写:
@app.get("/holidays")
def getHolidays():
session = Session(bind=engine)
holidays: List[Holiday] = session.query(Holiday).all()
return [x.to_json() for x in holidays]
@app.get("/exclusive_operations")
def getExclusiveOperations():
session = Session(bind=engine)
exclusive_operations: List[ExclusiveOperation] = session.query(ExclusiveOperation).all()
return [x.to_json() for x in exclusive_operations]
@app.get('/category_descriptions')
def getCategoryDescr():
session = Session(bind=engine)
category_descrs: List[CategoryDescr] = session.query(CategoryDescr).all()
return [x.to_json() for x in category_descrs]
所以如果我想创建所有的 crud 操作,我需要为 3 个实体创建 12 个典型方法。也许存在其他解决方案?
它是Python - 作为一种动态语言,函数和方法是在运行时创建的。 “@app.get”装饰器用于在应用程序中注册您的视图,而不是它们存在于模块的顶层。
因此,您可以创建一个 for 循环,为每个实体简单地重新创建和注册视图 - 它可以在模块级别或在函数内部完成。
(很高兴记住“@xxxx”装饰器语法只是调用装饰器的语法糖,将装饰函数作为唯一参数传递)
for Entity, name in [(Holiday, "holidays"), (ExclusiveOperation, "exclusive_operations"), (CategoryDescr, "category_descriptions")]:
def freeze_var_wrapper(Entity, name):
# this intermediary function is needed, otherwise the Entity and name
# variables would be always up-to-date inside the view function
# and always point to the last value in the external for-loop after
# it finished execution:
def view():
session = Session(bind=engine)
entities = session.query(Entity).all()
return [x.to_json() for x in entities]
# optional, may facilitate debugging:
view.__name__ = f"get{Entity.__name__}s"
# actually registers the view function with the framework:
# (could be done in the same line, without the "view_registrer" var)
view_registrer = app.get(f"/{name}")
view_registrer(view)
freeze_var_wrapper(Entity, name)
还有其他方法可以删除样板并看起来更优雅 - 例如 class 继承和适当的 __init__subclass__
在基础 class 中(即使框架不使用“class 视图”,我们也会为每个 class 注册绑定方法,这只是一个可调用的):
class BaseView:
Entity: cls
view_name: str
def __init_subclass__(cls, *args, **kw):
super().__init_subclass__(*args, **kw)
app.get(f"/{cls.view_name}")(cls.view)
# above, cls.view is bound to the subclass being processed, therefore
# the class attributes as defined in each class body are used inside the method
# this could easily register post, delete and detail views as well
@classmethod
def view(cls);
session = Session(bind=engine)
entities = session.query(cls.Entity).all()
return [x.to_json() for x in entities]
class HolydayView(BaseView):
Entity = Holyday
view_name = "holydays"
# thats is just it.
class ExclusiveOperationView(BaseView):
Entity = ExclusiveOperation
view_name = "exclusive_operations"
class CatewgoryDescriptionView(BaseView):
Entity = CategoryDescription
view_name = "category_descriptions"
我正在尝试使用 FastApi 和 sqlAchemy 创建后端应用程序。我有很多与数据库有关系的实体。所以,我的问题是:如何加快发展?现在我为每个实体代码编写:
@app.get("/holidays")
def getHolidays():
session = Session(bind=engine)
holidays: List[Holiday] = session.query(Holiday).all()
return [x.to_json() for x in holidays]
@app.get("/exclusive_operations")
def getExclusiveOperations():
session = Session(bind=engine)
exclusive_operations: List[ExclusiveOperation] = session.query(ExclusiveOperation).all()
return [x.to_json() for x in exclusive_operations]
@app.get('/category_descriptions')
def getCategoryDescr():
session = Session(bind=engine)
category_descrs: List[CategoryDescr] = session.query(CategoryDescr).all()
return [x.to_json() for x in category_descrs]
所以如果我想创建所有的 crud 操作,我需要为 3 个实体创建 12 个典型方法。也许存在其他解决方案?
它是Python - 作为一种动态语言,函数和方法是在运行时创建的。 “@app.get”装饰器用于在应用程序中注册您的视图,而不是它们存在于模块的顶层。
因此,您可以创建一个 for 循环,为每个实体简单地重新创建和注册视图 - 它可以在模块级别或在函数内部完成。
(很高兴记住“@xxxx”装饰器语法只是调用装饰器的语法糖,将装饰函数作为唯一参数传递)
for Entity, name in [(Holiday, "holidays"), (ExclusiveOperation, "exclusive_operations"), (CategoryDescr, "category_descriptions")]:
def freeze_var_wrapper(Entity, name):
# this intermediary function is needed, otherwise the Entity and name
# variables would be always up-to-date inside the view function
# and always point to the last value in the external for-loop after
# it finished execution:
def view():
session = Session(bind=engine)
entities = session.query(Entity).all()
return [x.to_json() for x in entities]
# optional, may facilitate debugging:
view.__name__ = f"get{Entity.__name__}s"
# actually registers the view function with the framework:
# (could be done in the same line, without the "view_registrer" var)
view_registrer = app.get(f"/{name}")
view_registrer(view)
freeze_var_wrapper(Entity, name)
还有其他方法可以删除样板并看起来更优雅 - 例如 class 继承和适当的 __init__subclass__
在基础 class 中(即使框架不使用“class 视图”,我们也会为每个 class 注册绑定方法,这只是一个可调用的):
class BaseView:
Entity: cls
view_name: str
def __init_subclass__(cls, *args, **kw):
super().__init_subclass__(*args, **kw)
app.get(f"/{cls.view_name}")(cls.view)
# above, cls.view is bound to the subclass being processed, therefore
# the class attributes as defined in each class body are used inside the method
# this could easily register post, delete and detail views as well
@classmethod
def view(cls);
session = Session(bind=engine)
entities = session.query(cls.Entity).all()
return [x.to_json() for x in entities]
class HolydayView(BaseView):
Entity = Holyday
view_name = "holydays"
# thats is just it.
class ExclusiveOperationView(BaseView):
Entity = ExclusiveOperation
view_name = "exclusive_operations"
class CatewgoryDescriptionView(BaseView):
Entity = CategoryDescription
view_name = "category_descriptions"