如何通过SQLalchemy的声明式方法描述关联对象
我想找一种方法,用声明式的方式来描述一个关联对象。除了在关联表中存储外键之外,我还需要存储一些信息,比如关联的创建日期。
现在,我的模型是这样的:
# Define the User class
class User(Base):
__tablename__ = 'users'
# Define User fields
id = schema.Column(types.Integer(unsigned=True),
schema.Sequence('users_seq_id', optional=True), primary_key=True)
password = schema.Column(types.Unicode(64), nullable=False)
# Define the UserSubset class
class UserSubset(Base):
__tablename__ = 'subsets'
# Define UserSubset fields
id = schema.Column(types.Integer(unsigned=True),
schema.Sequence('subsets_seq_id', optional=True), primary_key=True)
some_short_description = schema.Column(types.Unicode(50), nullable=False)
# Define the subset memberships table
subset_memberships = schema.Table('group_memberships', Base.metadata,
schema.Column('user_id', types.Integer(unsigned=True), ForeignKey('users.id')),
schema.Column('subset_id', types.Integer(unsigned=True), ForeignKey('subsets.id')),
schema.Column('created', types.DateTime(), default=now, nullable=False),
)
我可以把所有东西都连接到一个关联对象上吗?还是说我应该放弃使用声明式的方法?
2 个回答
0
从手册中可以看到,设置一对多的关系其实非常简单:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
addresses = relation("Address", backref="user")
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email = Column(String(50))
user_id = Column(Integer, ForeignKey('users.id'))
多对多的关系也不难:
使用声明式(declarative)来处理多对多关系没有什么特别的。relation()函数的第二个参数仍然需要一个表对象,而不是一个声明式类。这个表应该和声明式基础使用的MetaData对象是同一个:
keywords = Table('keywords', Base.metadata, Column('author_id', Integer, ForeignKey('authors.id')), Column('keyword_id', Integer, ForeignKey('keywords.id')) ) class Author(Base): __tablename__ = 'authors' id = Column(Integer, primary_key=True) keywords = relation("Keyword", secondary=keywords)
一般来说,在多对多关系中,你不应该同时映射一个类和指定它的表,因为这样可能会导致ORM发出重复的插入和删除语句。
总之,你现在的做法可能更适合使用继承。当然,有些复杂的表关系可能会让声明式的方式变得很麻烦,但看起来这并不是其中之一。
还有一点,代码注释应该说明接下来的代码做了什么以及为什么,而不是怎么做。比如说,写一个 # 定义用户类
的注释,几乎就像在代码里写 a = 1 # 将值1赋给变量"a"
一样。
1
你现在使用的只是一个多对多的关系。关于如何使用关联对象的详细信息,可以在文档中找到。
还有一个叫做associationproxy的扩展,它可以简化这种关系。