sqlalchemy 使用变量来定义列

sqlalchemy use variable for column definition

假设我有很多模型都使用相同类型的列。例如

class PurchaseOrder(Model):
    unitprice = Column(Numeric(10,2))
    ...other columns

class SalesOrder(Model):
    salesprice = Column(Numeric(10,2))
    ...other columns

我想定义一些变量;

currencyamount = Column(Numeric(10,2))

然后,如果定义发生变化,我将只有一个地方可以修复它。我希望模型定义现在看起来像这样。

class PurchaseOrder(Model):
    unitprice = currencyamount
    ...other columns

如果我尝试这样做,我会收到一条错误消息“列对象 'unitprice' 已分配给 Table PurchaseOrder。”

我该怎么做?

我通常使用一个函数,然后调用它来生成该列。另一个好处是您可以添加参数来自定义列配置。

def currencyamount_col():
    return Column(Numeric(10,2))

#...

class PurchaseOrder(Model):
    unitprice = currencyamount_col()
    # ...other columns

这是我使用的日期列工厂:


def dt_column(default_now=True, onupdate_now=False, **override_col_kwargs):
    dt_kwargs = {
        "timezone": True
    }
    dt = DateTime(**dt_kwargs)
    col_kwargs = {}
    if default_now:
        col_kwargs['default'] = utc_now
    if onupdate_now:
        col_kwargs['onupdate'] = utc_now
    col_kwargs.update(override_col_kwargs)
    return Column(dt, **col_kwargs)

您的对象已在应用程序周围共享。它与每个 class 使用的引用相同。也许你应该尝试使用工厂方法:

class PurchaseOrder(Model):
    unitprice = get_currency_column()
    ...other columns

get_currency_column():
    return Column(Numeric(10,2))

但坦率地说,我对列定义如此频繁地更改感到惊讶。

我认为最简洁的方法是只创建一个包含通用属性定义的抽象 Order 基础 class,然后为您的不同订单类型创建子class。

SQLAlchemy 允许您创建一个基数 class,它不会通过 __abstract__ 指示符在数据库中表示。您可以在此 class 上定义公共属性。阅读更多 here

像这样的东西应该适合你:

class Order(Model):
    __abstract__ = True
    unitprice = Column(Numeric(10,2))

class PurchaseOrder(Order):
    ...other columns

class SalesOrder(Order):
    ...other columns

unitprice 列将由两个子class继承。