如何在sqlalchemy.orm.synonym中使用描述符
我有一段代码,运行得很好:
def get_timestamp(ts):
return datetime.utcfromtimestamp(ts)
def set_timestamp(dt):
return time.mktime(dt.timetuple())
class Group(Base):
__tablename__ = 'group'
_created = Column('created', Integer, nullable=False)
@property
def created(self):
return get_timestamp(self._created)
@created.setter
def created(self, value):
self._created = set_timestamp(value)
我想要一段类似的代码,但它却不工作:
created = synonym('_created',
descriptor=property(get_timestamp,
set_created))
因为它总是把一个 self
作为第一个参数传进去。
我想在我的项目中使用 get_timestamp
和 set_timestamp
,所以我不打算把它们做成类的方法,而是想让它们成为独立的函数。
我该怎么做呢?
补充说明:我会选择第二种方案,并且仍然欢迎其他的建议。
2 个回答
0
我现在使用的是一种不同的实现方式。这和最初的标题没关系,但如果你需要的话,可以参考一下。
使用 sqlalchemy.types.TypeDecorator
。 用sqlalchemy定义一个包含mysql Unix时间戳的表
class UTCTimestampType(TypeDecorator):
impl = Integer
def process_bind_param(self, value, dialect):
if value is None:
return None # support nullability
elif isinstance(value, datetime):
return int(time.mktime(value.timetuple()))
raise ValueError("Can operate only on datetime values. Offending value type: {0}".format(type(value).__name__))
def process_result_value(self, value, dialect):
if value is not None: # support nullability
return datetime.fromtimestamp(float(value))
class ModelA(Base):
__tablename__ = 'model_a'
id = Column(Integer, primary_key=True)
created = Column(UTCTimestampType, nullable=False)
关于alembic的问题。 Alembic:如何在模型中迁移自定义类型?
# manually change the line
sa.Column('created', sa.UTCTImestampType(), nullable=False),
# to
sa.Column('created', sa.Integer(), nullable=False),
1
选项1: 下面的代码应该可以正常工作(你不需要有一个类来定义 self
):
def pget_timestamp(self):
return datetime.utcfromtimestamp(self._created)
def pset_timestamp(self, dt):
self._created = time.mktime(dt.timetuple())
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
_created = Column('created', Integer, nullable=False)
created = synonym(_created,
descriptor=property(pget_timestamp, pset_timestamp),
)
选项2: 如果你需要在很多类中使用相同的功能,可以利用Mixins
。
from sqlalchemy.ext.declarative import declared_attr
class _CreatedMixin(object):
_created = Column('created', Integer, nullable=False)
def pget_timestamp(self):
return datetime.utcfromtimestamp(self._created)
def pset_timestamp(self, dt):
self._created = time.mktime(dt.timetuple())
@declared_attr
def created(cls):
return synonym('_created',
descriptor=property(cls.pget_timestamp, cls.pset_timestamp),
)
class Group(_CreatedMixin, Base):
# @note: adding *_CreatedMixin* to bases defines both the column and the synonym
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
另外,如果这个功能是针对你所有的类,你可以把 _CreatedMixin
作为所有模型的基类:
Base = declarative_base(engine, cls=_CreatedMixin)
class Group(Base):
__tablename__ = 'group'
id = Column(Integer, primary_key=True)
选项3: 你可以使用Hybrid Attributes
来实现以上任何一种方法。
注意:确保你的设置/获取函数保持一致:要么都使用UTC功能,要么都不使用。目前(除非你在UTC-0时),设置一个值为 created
不会返回相同的值。