SQLAlchemy

时间:2015-05-21 00:05:08

标签: python transactions sqlalchemy

我有一个集合类,用于使用SQLAlchemy修改DB中的某些数据:

import sqlalchemy as sa

class Collection:
    def __init__(self, ...):
        self.engine = sa.create_engine(...)

    def get_some_name_by_id(self, name):
        return self.engine.execute(select(), ...).fetchone().id

    def add(self, name):
        some_id = self.get_some_name_by_id(name)
        with self.engine.begin() as conn:
            conn.execute(...)
            conn.execute(...)
            conn.execute(...)
            ...

所以它有两种方法:

  • get_some_name_by_id - 给定名称返回一些id
  • add方法使用get_some_name_by_id中的id来执行一系列SQL请求。

问题是我想在事务中加入get_some_name_by_id。起初我有一个巨大的add方法,其中所有execute语句都在with语句下。现在我通过向方法中提取一些块来重构代码,我不知道如何将它们添加到事务中。如果在事务中调用它,则可以在事务中运行该方法。

当然,我可以这样做:

def get_some_name_by_id(self, name, conn=None):
    if conn is None:
        conn = self.engine
    return conn.execute(select(), ...).fetchone().id

def add(self, name):
    with self.engine.begin() as conn:
        some_id = self.get_some_name_by_id(name, conn)
        conn.execute(...)

但对我来说这看起来有点笨拙。我最终会得到很多具有相同if条款的函数。有没有更好的办法?

1 个答案:

答案 0 :(得分:0)

我认为你建议的方法没问题。您可以使用@property装饰器来实现conn的自定义检索: 例如:

import sqlalchemy as sa

class Collection(object):
    def __init__(self, ...):
        self.engine = sa.create_engine(...)
        self._conn = None

    @property
    def conn(self):
        if self._conn is None:
            self._conn = self.engine
        return self._conn

    @conn.setter
    def conn(self, value):
        self._conn = value

    def get_some_name_by_id(self, name):
        return self.conn.execute(select(), ...).fetchone().id

    def add(self, name):
        with self.engine.begin() as self.conn:
            some_id = self.get_some_name_by_id(name)
            self.conn.execute(...)

这样你就不必通过conn了。您可以初始化self.conn一次并使用它使用此按钮,您将被限制为每个Collection对象一个连接。您可以修改它以支持多个连接(如果需要)。