Mar*_*ian 9 python orm sqlalchemy data-conversion
在我的数据库中,我有一些列,其中数据以某种奇怪的格式存储.由于数据库也被其他代码使用,我无法更改数据格式.
例如,一种奇怪的格式是时间值表示为字符串23:42:30.我想有一些魔法可以让我总是datetime.time在python端使用对象.
一个非常简单的解决方案是:
col_raw = Column('col', String(7))
@property
def col(self):
return datetime.strptime(self.col_raw, '%H:%M:%S').time()
@col.setter
def colself, t):
self.col_raw = t.strftime('%H:%M:%S')
Run Code Online (Sandbox Code Playgroud)
但是,这只能解决读写数据的问题.像这样的东西是不可能的:
Table.query.filter(Table.col == time(23,42,30))
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用混合扩展.这样,查询就有可能,但如果我看得正确,写不会.此外,它需要编写两次编码,一次是在python代码中,一次是在SQL代码中.(其他问题:我不确定转换是否只能使用SQL代码编写.)
真的没有办法将两者结合起来吗?比如我定义了两个功能,比方说python2sql和sql2python,这SQLAlchemy的使用从Python对象的值转换透明地向字符串和后面?我知道,这会使一些查询不可能的,比如between或like或款项之类的,不过没关系.
请记住,时间只是我需要转换数据的情况之一; 所以请尽量保持回复的通用性.
dav*_*ism 14
使用类型装饰器来处理与自定义格式之间的转换.使用此类型而不是String定义列时.
class MyTime(TypeDecorator):
impl = String
def __init__(self, length=None, format='%H:%M:%S', **kwargs)
super().__init__(length, **kwargs)
self.format = format
def process_literal_param(self, value, dialect):
# allow passing string or time to column
if isinstance(value, basestring): # use str instead on py3
value = datetime.strptime(value, self.format).time()
# convert python time to sql string
return value.strftime(self.format) if value is not None else None
process_bind_param = process_literal_param
def process_result_value(self, value, dialect):
# convert sql string to python time
return datetime.strptime(value, self.format).time() if value is not None else None
# in your model
class MyModel(Base):
time = Column(MyTime(length=7))
Run Code Online (Sandbox Code Playgroud)