我正在编写Python应用程序以使用SQLAlchemy在Postgres数据库上运行。在settings.py
DATABASE = {
'drivername': 'postgres',
'host': 'xyz.com',
'port': '5432',
'username': 'user',
'password': 'pass',
'database': 'db_dev'
}
然后我使用创建连接的方法创建了db_connection.py
。
from sqlalchemy import *
from sqlalchemy.engine.url import URL
from . import settings
def get_engine():
return create_engine(URL(**settings.DATABASE))
我想让另一个模块db_ops.py
具有所有数据库操作func1
,func2
方法,并在主应用程序模块中调用它们
engine = db.connection.get_engine()
db_ops.func1()
db_ops.func2()
这意味着我需要将engine
作为参数传递给这些方法。
func1(engine)
func2(engine)
不知怎的,我不喜欢将db连接作为方法参数。有没有更好的方法呢?
答案 0 :(得分:0)
Engine
不连接。您可以将其视为连接池。通常,使用引擎的最自然方式是将其置于全局级别。在您的情况下,您可以将其放在db_connection.py
:
from sqlalchemy import *
from sqlalchemy.engine.url import URL
from . import settings
engine = create_engine(URL(**settings.DATABASE))
然后,您可以在db_ops
模块中导入它:
from db_connection import engine
def func1():
engine.execute(...)
但是,对于一系列相关查询,您可能希望在单个事务中执行它们,这需要传递实际连接:
with engine.begin() as connection:
func1(connection)
func2(connection)
要解决这个问题,我们有scoped_session
的概念(同样,在全球范围内):
engine = create_engine(URL(**settings.DATABASE))
Session = scoped_session(sessionmaker(bind=engine))
每次调用Session
时,它都会检查当前线程是否已有会话,如果不是,则创建会话,从而无需传递连接:
from db_connection import Session
def func1():
Session.execute(...)
在db_ops
个函数的调用方中:
try:
func1()
func2()
Session.commit()
finally:
Session.remove()