我试图让以下模型一起工作。首先的情况如下:彼此依赖的一对多关系SQLAlchemy
- 用户可以有多个电子邮件地址,但每个电子邮件地址只能与一个用户相关联;
- 每个用户只能有一个主电子邮件地址(认为它像他们当前的电子邮件地址)。
电子邮件地址是用户的ID,所以他们必须总是有一个,但是当他们改变它时,我想跟踪他们过去使用过的其他人。到目前为止,该设置是有一个助手表user_emails
,其中包含一个电子邮件和用户之间的联系,我听说不应该设置为使用声明式SQLAlchemy方法的类(尽管我不知道为什么)。另外,我是否认为我需要使用use_alter=True
,因为在插入之前,users
表将不知道外键email_id
?
models.py
看起来是这样的:
"""models.py"""
user_emails = Table('user_emails', Base.metadata,
Column('user_id', Integer, ForeignKey('users.id'),
primary_key=True),
Column('email', String(50), ForeignKey('emails.address'),
primary_key=True))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, Sequence('usr_id_seq', start=100, increment=1),
primary_key=True)
email_id = Column(String(50),
ForeignKey('emails.address', use_alter=True, name='fk_email_id'),
unique=True, nullable=False)
first = Column(String(25), unique=True, nullable=False)
last = Column(String(25), unique=True, nullable=False)
def __init__(self, first, last):
self.first = first
self.last = last
class Email(Base):
__tablename__ = 'emails'
address = Column(String(50), unique=True, primary_key=True)
user = relationship(User, secondary=user_emails, backref='emails')
added = Column(DateTime, nullable=False)
verified = Column(Boolean, nullable=False)
def __init__(self, address, added, verified=False):
self.address = address
self.added = added
self.verified = verified
似乎一切都OK,直到我尝试提交到DB:
>>> user = models.User("first", "last")
>>> addy = models.Email("[email protected]", datetime.datetime.utcnow())
>>> addy
<Email '[email protected]' (verified: False)>
>>> user
>>> <User None (active: True)>
>>>
>>> user.email_id = addy
>>> user
>>> <User <Email '[email protected]' (verified: False)> (active: True)>
>>> Session.add_all([user, addy])
>>> Session.commit()
>>> ...
>>> sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'Email' "INSERT INTO users (id, email_id, first, last, active) VALUES (nextval('usr_id_seq'), %(email_id)s, %(first)s, %(last)s, %(active)s) RETURNING users.id" {'last': 'last', 'email_id': <Email '[email protected]' (verified: False)>, 'active': True, 'first': 'first'}
所以,我认为我做错了什么/愚蠢,但我是SQLAlchemy的新手,所以我不确定我需要做什么才能正确设置模型。
最后,假设我获得了正确的模型设置,是否可以添加一个关系,以便通过加载任意电子邮件对象,我可以从Email对象的属性访问拥有它的用户?
谢谢!
这是一个很好的答案,谢谢!将'Email'分配给'User'中的'email_id'是我的一个错字 - 我想这解释了编程错误异常?我打算使用您的解决方案的第二版。 PS - 'use_alter'是否需要在给定的位置,正如你所说的,关键是地址(而不是自动增量?)。 – Edwardr 2012-04-24 08:33:35
正如我所提到的,你的代码不需要'use_alter = True'。 – van 2012-04-24 08:38:43