我试图让以下模型一起工作。首先,场景如下:
- 一个用户可以有多个邮箱,但每个邮箱只能关联一个用户;
- 每个用户只能有一个主电子邮件地址(将其视为他们当前的电子邮件地址)。
电子邮件地址是用户的 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
在我尝试提交数据库之前,一切似乎都很好:
>>> user = models.User("first", "last")
>>> addy = models.Email("example@example.com", datetime.datetime.utcnow())
>>> addy
<Email 'example@example.com' (verified: False)>
>>> user
>>> <User None (active: True)>
>>>
>>> user.email_id = addy
>>> user
>>> <User <Email 'example@example.com' (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 'example@example.com' (verified: False)>, 'active': True, 'first': 'first'}
所以,我认为我做错了/愚蠢,但我是 SQLAlchemy 的新手,所以我不确定我需要做什么才能正确设置模型。
最后,假设我设置了正确的模型,是否可以添加关系,以便通过加载任意电子邮件对象,我将能够从电子邮件对象中的属性访问拥有它的用户?
谢谢!