【发布时间】:2019-01-29 17:07:19
【问题描述】:
我正在使用 Flask 和 SQLAlchemy(通过 Flask-SQLAlchemy;使用 MySQL 或 SQLite)在 Python 3 中构建一个 Web 应用程序,我遇到了一种情况,我想在我的在我的数据库中封装多个列的模型类。我非常精通 MySQL,但这是我第一次真正涉足 SQLAlchemy,超出了基础。阅读文档、搜索 SO 和搜索 Google 让我找到了两种可能的解决方案:混合属性 (docs) 或复合列 (docs)。
我的问题是,使用这些方法的含义是什么?哪一种方法适合我的情况?我在下面包含了示例代码,这是我正在做的事情。
背景:我正在开发一个应用程序来跟踪和排序照片,并有一个数据库表,用于存储这些照片的元数据,包括照片的拍摄时间。由于照片是在特定地点拍摄的,因此拍摄的日期和时间具有关联的时区。由于 SQL 与时区有着众所周知的爱/恨关系,我选择在两列中记录照片的拍摄时间:存储日期和时间的日期时间和存储时区名称的字符串。 (我想回避关于如何在 SQL 中存储时区感知日期和时间的不可避免的争论。)我想要的是模型类上的单个参数,我可以使用它来获取正确的 python 日期时间对象,并且我也可以像任何其他列一样设置。
这是我的桌子:
class Photo(db.Model):
__tablename__ = 'photos'
id = db.Column(db.Integer, primary_key=True)
...
taken_dt = db.Column(db.datetime, nullable=False)
taken_tz = db.Column(db.String(64), nullable=False)
...
这是我使用混合参数(添加到上面的类,datetime/pytz 代码是伪代码):
@hybrid_parameter
def taken(self):
return datetime.datetime(self.taken_dt, self.taken_tz)
@taken.setter(self, dt):
self.taken_dt = dt
self.taken_tz = dt.tzinfo
从那里我不确定我还需要@taken.expression 或@taken.comparator 的方式,或者为什么我会选择其中一个。
这是我使用复合列的内容(再次,添加到上面的类中,datetime/pytz 代码是伪代码):
taken = composite(DateTimeTimeZone._make, taken_dt, taken,tz)
class DateTimeTimeZone(object):
def __init__(self, dt, tz):
self.dt = dt
self.tz = tz
@classmethod
def from_db(cls, dt, tz):
return DateTimeTimeZone(dt, tz)
@classmethod
def from_dt(cls, dt):
return DateTimeTimeZone(dt, dt.tzinfo)
def __composite_values__(self):
return (self.dt, self.tz)
def value(self):
#This is here so I can get the actual datetime.datetime object
return datetime.datetime(self.dt, self.tz)
看起来这个方法有相当多的额外开销,我想不出一种方法来设置它,就像我直接从 datetime.datetime 对象中的任何其他列一样,而不首先使用 @ 实例化值对象987654328@.
欢迎任何关于我是否走错路的指导。谢谢!
【问题讨论】:
标签: python sqlalchemy