如何通过装饰器向类中添加静态字段?

时间:2016-04-07 13:59:49

标签: python sqlalchemy python-decorators

我遇到sqlalchemy和旧数据库的问题。假设我有类似的模型

class A(Base):
    foo = Column(String)
    modified_at = Column(DateTime, default=func.now, onupdate=func.now())

class B(Base):
    bar = Column(String)
    modified_at = Column('SOME_NAME', DateTime, default=func.now, onupdate=func.now())

正如您所看到的,modified_at字段中存在代码重复。这两个类都有modified_at字段来跟踪上次修改的时间,但具有不同的列名。

这可以使用元类来解决,但它实际上需要基本相同数量的代码来传递列名,因为它与使用代码重复的解决方案一样(特别是在python2中,因为在python2中你不能将参数传递给元类)容易)

所以我想到的是使用decorate类

def modified_at(col_name=None):
    def decorator(cls):
        cls.modified_at = Column(col_name, Datetime) # etc
        return cls
return decorator

@modified_at('SOME_NAME')
class B(Base):
    bar = Column(String)

但是这在实例化B时会给我错误(bar ='某些值')

TypeError decorator() got an unexpected keyword argument 'bar'

1 个答案:

答案 0 :(得分:0)

你仍然可以使用mixin。来自SQLAlchemy文档:http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/mixins.html#mixing-in-columns

class TimestampMixin(object):
    created_at = Column(DateTime, default=func.now())

class MyModel(TimestampMixin, Base):
    __tablename__ = 'test'

    id =  Column(Integer, primary_key=True)
    name = Column(String(1000))

相反,定义一个返回mixin的函数:

def custom_mixin(param):
    class MyMixin(object):
        created_at = Column(DateTime, param, default=func.now())
    return MyMixin

class MyModel(custom_mixin('foobar'), Base):
    __tablename__ = 'test'

    id =  Column(Integer, primary_key=True)
    name = Column(String(1000))

您也可以定义一个函数来返回已配置的Column()对象,并正常配置该类。