9

以下に示すように、多対多の関係にある 2 つのテーブルがあるとします。

class User(db.Model):
  __tablename__ = 'user'
  uid = db.Column(db.String(80), primary_key=True)
  languages = db.relationship('Language', lazy='dynamic',
                              secondary='user_language')

class UserLanguage(db.Model):
  __tablename__ = 'user_language'
  __tableargs__ = (db.UniqueConstraint('uid', 'lid', name='user_language_ff'),)

  id = db.Column(db.Integer, primary_key=True)
  uid = db.Column(db.String(80), db.ForeignKey('user.uid'))
  lid = db.Column(db.String(80), db.ForeignKey('language.lid'))

class Language(db.Model):
  lid = db.Column(db.String(80), primary_key=True)
  language_name = db.Column(db.String(30))

今pythonシェルで:

In [4]: user = User.query.all()[0]

In [11]: user.languages = [Language('1', 'English')]

In [12]: db.session.commit()

In [13]: user2 = User.query.all()[1]

In [14]: user2.languages = [Language('1', 'English')]

In [15]: db.session.commit()

IntegrityError: (IntegrityError) column lid is not unique u'INSERT INTO language (lid, language_name) VALUES (?, ?)' ('1', 'English')

重複を無視し、Language テーブルの一意の制約を破ってはならないことをリレーションシップに知らせるにはどうすればよいですか? もちろん、各言語を個別に挿入して、エントリがテーブルに既に存在するかどうかを事前に確認することもできますが、そうすると、sqlalchemy の関係によって提供されるメリットの多くが失われます。

4

2 に答える 2

8

SQLAlchemy wiki には一連の例があり、その 1 つはインスタンスの一意性をチェックする方法です。

ただし、例は少し複雑です。基本的にget_unique、代替コンストラクターとしてクラスメソッドを作成します。これは、最初にセッションキャッシュをチェックし、次に既存のインスタンスに対してクエリを試行し、最後に新しいインスタンスを作成します。Language.get_unique(id, name) 次に、代わりに呼び出しますLanguage(id, name)

別の質問に対するOPの報奨金に応えて、より詳細な回答を書きました。

于 2013-12-30T05:46:10.677 に答える