我正在开发一个在后端有10个左右的表格的Web API,有几个一对多和多对多的关联。 API本质上是一个执行验证更新和条件查询的数据库包装器。它是用Python编写的,我使用SQLAlchemy进行ORM,使用CherryPy进行HTTP处理。
到目前为止,我已将API执行的30个查询分离为自己的函数,如下所示:
# in module "services.inventory"
def find_inventories(session, user_id, *inventory_ids, **kwargs):
query = session.query(Inventory, Product)
query = query.filter_by(user_id=user_id, deleted=False)
...
return query.all()
def find_inventories_by(session, app_id, user_id, by_app_id, by_type, limit, page):
....
# in another service module
def remove_old_goodie(session, app_id, user_id):
try:
old = _current_goodie(session, app_id, user_id)
services.inventory._remove(session, app_id, user_id, [old.id])
except ServiceException, e:
# log it and do stuff
....
CherryPy请求处理程序根据需要调用分散在多个服务模块中的查询方法。这个解决方案背后的基本原理是,由于它们需要访问多个模型类,因此它们不属于单个模型,并且这些数据库查询也应该与API访问的直接处理分开。
我意识到上面的代码可能在重构领域被称为Foreign Methods。我可以用这种组织方式生活一段时间,但随着事情开始变得有些混乱,我正在寻找一种方法来重构这段代码。
session
参数,但是因为API的当前实现为每个API调用创建一个新的CherryPy处理程序实例,因此session
对象,没有全局方式获得当前session
。是否有完善的模式来组织此类查询?我应该坚持使用外来方法,并尝试统一函数签名(参数排序,命名约定等)?你会建议什么?
答案 0 :(得分:1)
SQLAlchemy强烈建议会话制作者参与某些全局配置。
这是sessionmaker()的意图 函数在全局范围内调用 申请范围和 返回课程可供使用 其余的应用程序作为 用于实例化的单个类 会话。
在单独模块中的查询不是一个有趣的问题。 Django ORM以这种方式工作。一个网站通常由多个Django“应用程序”组成,这听起来像您的网站有许多“服务模块”。
将多个服务编织在一起是应用程序的重点。没有很多替代方案更好。
答案 1 :(得分:1)
在线程环境中对当前会话进行全局访问的标准方法是ScopedSession。在与框架集成时,有一些重要方面可以正确实现,主要是事务控制和清除请求之间的会话。一个常见的模式是在模块中有一个autocommit = False(默认值)ScopedSession,并将任何业务逻辑执行包装在try-catch子句中,该子句在异常情况下回退并在方法成功时提交,然后最终调用Session.remove ()。然后,业务逻辑将Session对象导入全局范围,并像常规会话一样使用它。
似乎存在CherryPy-SQLAlchemy integration module,但由于我对CherryPy不太熟悉,我无法对其质量发表评论。
将查询封装为函数就可以了。并非一切都需要在课堂上。如果它们太多而只是按主题分成单独的模块。
我发现有用的东西也是常见的标准片段。它们通常适合作为模型类的类方法。除了提高可读性和减少重复之外,它们还可以作为实现在某种程度上隐藏抽象,使重构数据库变得不那么痛苦。 (示例:代替(Foo.valid_from <= func.current_timestamp()) & (Foo.valid_until > func.current_timestamp())
您有Foo.is_valid()
)