【发布时间】:2017-06-05 07:02:57
【问题描述】:
动机
举一个简单的例子,其中一列数据需要用 SQL 中的枚举类型来表示:
+------------------------------------------+
| user |
+----+------+-----+------------------------+
| id | name | age | relationship_status_id |
+----+------+-----+------------------------+
| 1 | John | 27 | 3 |
| 2 | Mary | 77 | 1 |
| 3 | Jack | 40 | 4 |
+----+------+-----+------------------------+
+---------------------+
| relationship_status |
+----+----------------+
| id | name |
+----+----------------+
| 1 | married |
| 2 | widowed |
| 3 | single |
| 4 | divorced |
+----+----------------+
在 SQLAlchemy 中定义(声明)表本身相对简单:
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
relationship_status_id = Column(Integer, ForeignKey('relationship_status.id'))
class RelationshipStatus(Base):
__tablename__ = 'relationship_status'
id = Column(Integer, primary_key=True)
name = Column(String)
初始化数据库时,可以使用Base.metadata.create_all(engine) 指令创建表。 user 表将在应用程序的运行生命周期内填充;但是,relationship_status 查找表的数据保持不变,将这些数据与表定义一起“声明”似乎是合适的。
然而,将数据持久化到表中自然需要session,并且与表定义本身不同,SQLAlchemy 似乎没有为给定表中的“预期行”提供任何声明性构造(当然,因为大多数表在任何应用程序都像 user 与动态数据)。
问题
使用 SQLAlchemy,如何在应用程序运行前声明查找表的模式和数据?理想情况下,该解决方案将涉及创建一些类似 Enum 的构造,其中包含应用程序其他部分可以引用的数据。
研究
SQLAlchemy 的创建者提出了the enum recipe。这种解决方案唯一明显的缺点是必须依赖正在使用的 DBMS 中的 enum 数据类型。对于这个问题的范围,首选独立于 DBMS 的查找表解决方案。
SQLAlchemy 的创建者还提出了一个相关的替代方案是the unique object recipe。这样的实现确保了查找表查询返回的行没有重复,但是仍然需要一个session 对象来进行任何声明或请求——模糊了数据库定义和实现之间的关注点分离。此外,客户端都只需要“只知道”要请求哪些行,而不是使用某种枚举(在 Python 中)以供参考。
问题的根源可能是概念性的,而不是与 SQLAlchemy 或 Python 相关。在任何一种情况下,任何建议都将不胜感激。
【问题讨论】:
标签: python enums sqlalchemy