次のモデルを連携させようとしています。まず、シナリオは次のとおりです。
- ユーザーは多数の電子メール アドレスを持つことができますが、各電子メール アドレスは 1 人のユーザーにのみ関連付けることができます。
- 各ユーザーは、プライマリ メール アドレスを 1 つだけ持つことができます(現在のメール アドレスのようなものと考えてください)。
メール アドレスはユーザーの ID であるため、常に 1 つ持っている必要がありますが、ユーザーが変更した場合は、過去に使用した他のものを追跡したいと考えています。これまでのところ、セットアップは、電子メールとユーザーの間の関係を保持するヘルパー テーブル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
DB にコミットしてみるまでは、すべて問題ないようです。
>>> 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に慣れていないので、モデルを正しくセットアップするために何をする必要があるのか わかりません。
最後に、適切なモデルをセットアップしたと仮定して、関係を追加して、任意の電子メール オブジェクトをロードすることで、電子メール オブジェクトの属性から、それを所有するユーザーにアクセスできるようにすることは可能ですか?
ありがとう!