flask-sqlalchemy或sqlalchemy
我是烧瓶和sqlalchemy的新手,我刚刚开始烧瓶应用程序,现在我正在使用sqlalchemy。 我想知道使用flask-sqlalchemy vs sqlalchemy是否有什么好处。 我找不到足够的动机在http://packages.python.org/Flask-SQLAlchemy/index.html或者我不明白的价值! 我希望你的澄清。
Flask-SQLAlchemy
的主要function是与Flask应用程序的正确集成 – 它创build和configuration引擎,连接和会话,并configuration它与Flask应用程序一起工作。
这个设置非常复杂,因为我们需要创build范围会话并根据Flask应用程序请求/响应生命周期正确处理它。
在理想的世界里,这将是Flask-SQLAlchemy
的唯一特征,但实际上它增加了更多的东西。 这里有一个很好的博客文章,其中包括: 揭秘Flask-SQLAlchemy 。
当我第一次使用Flask和SQLAlchemy时,我不喜欢这个开销。 我继续从扩展中提取会话pipe理代码。 这种方法很有效,但是我发现很难做到这一点。
所以更简单的方法(在另一个我正在使用的项目中使用的方法)是放弃Flask-SQLAlchemy
,不要使用它提供的任何附加function。 你将拥有db.session
,你可以像使用纯SQLAlchemy
设置一样使用它。
SQLAlchemy文档明确指出,你应该使用Flask-SQLAlchemy(特别是如果你不明白它的好处!):
Flask-SQLAlchemy […] SQLAlchemy等产品强烈build议将这些产品用作可用的产品。
这个引用和详细的动机你可以在Session FAQ的第二个问题中find。
说实话,我没有看到任何好处。 恕我直言,Flask-SQLAlchemy创build了一个你并不需要的附加层。 在我们的例子中,我们有一个相当复杂的Flask应用程序,它有多个使用ORM和Core的数据库/连接(主 – 从),其中,我们需要控制会话/数据库事务(例如dryrun和commit模式)。 Flask-SQLAlchemy增加了一些额外的function,比如自动销毁会话,假设你有一些东西,这通常不是你所需要的。
正如@schlamar所说,Flask-SqlAlchemy是一个好东西。 我只是想添加一些额外的背景,在那里做的。
不要觉得你正在select一个。 例如,假设我们想要使用Flask-Sqlalchemy模型从表中获取所有logging。 这很简单
Model.query.all()
对于很多简单的情况,Flask-Sqlalchemy将会是完全正确的。 我想说的另一点是,如果Flask-Sqlalchemy不会做你想做的事,那么没有理由你不能直接使用SqlAlchemy。
from myapp.database import db num_foo = db.session.query(func.count(OtherModel.id)).filter(is_deleted=False).as_scalar() db.session.query(Model.id, num_foo.label('num_foo')).order_by('num_foo').all()
正如你所看到的,我们可以毫不费力地从一个跳到另一个,而在第二个例子中,我们实际上使用了Flask-Sqlalchemy定义的模型。
Flask-SQLAlchemy为您提供了一些不错的额外function,您最终还是可以使用SQLAlchemy来实现自己的function。
积极使用Flask-SQLAlchemy
- Flask_SQLAlchemy为您处理会话configuration,设置和拆卸。
- 为您提供了声明式的基础模型,使查询和分页更容易
- 后端特定设置.Flask-SQLAlchemy扫描已安装的库以支持Unicode,如果失败则自动使用SQLAlchemy Unicode。
- 有一个名为
apply_driver_hacks
的方法,它自动将默认值设置为像MySQL pool-size这样的thigs - 在方法create_all()和drop_all()方面有很好的构build,用于创build和删除所有表。 如果你做了一些愚蠢的事情,用于testing和python命令行
- 它提供了get_or_404()而不是get()和find_or_404()而不是find()代码示例,位于> http://flask-sqlalchemy.pocoo.org/2.1/queries/
自动设置表名。 Flask-SQLAlchemy自动设置你的表名来转换你的ClassName
> class_name
这可以通过设置__tablename__
class List项来覆盖
使用Flask-SQLAlchemy的消极方面
- 使用Flask-SQLAlchemy会增加额外的困难,从Flask迁移到让金字塔如果你需要。 这主要是由于Flask_SQLAchemy上的自定义声明基础模型。
- 使用Flask-SQLAlchemy可能会冒险使用一个比SQLAlchemy本身小得多的社区的包,我不能很快从活跃的开发中退出。
- 如果你不知道他们在那里,Flask-SQLAlchemy有一些很好的额外function可以让你感到困惑。
这里是一个利益的例子 – sqlalchemy让你在普通的sqlalchemy。
假设你正在使用flask_user。
flask_user自动创build和authentication用户对象,所以它需要访问你的数据库。 UserManager类通过调用一个称为“适配器”的抽象数据库调用来实现这一点。 您在UserManager构造函数中提供了一个适配器,并且适配器必须实现这些函数:
class MyAdapter(DBAdapter): def get_object(self, ObjectClass, id): """ Retrieve one object specified by the primary key 'pk' """ pass def find_all_objects(self, ObjectClass, **kwargs): """ Retrieve all objects matching the case sensitive filters in 'kwargs'. """ pass def find_first_object(self, ObjectClass, **kwargs): """ Retrieve the first object matching the case sensitive filters in 'kwargs'. """ pass def ifind_first_object(self, ObjectClass, **kwargs): """ Retrieve the first object matching the case insensitive filters in 'kwargs'. """ pass def add_object(self, ObjectClass, **kwargs): """ Add an object of class 'ObjectClass' with fields and values specified in '**kwargs'. """ pass def update_object(self, object, **kwargs): """ Update object 'object' with the fields and values specified in '**kwargs'. """ pass def delete_object(self, object): """ Delete object 'object'. """ pass def commit(self): pass
如果您使用的是flask-sqlalchemy,则可以使用内置的SQLAlchemyAdapter。 如果您使用的是sqlalchemy(not-flask-sqlalchemy),您可能会对将对象保存到数据库的方式做出不同的假设(如表的名称),因此您必须编写自己的适配器类。