4

docs の例と非常によく似たシナリオで、タグに関連付けプロキシを使用しようとしています。これは、宣言型を使用した私のスキーマ (ブログです) のサブセットです。

class Tag(Base):
    __tablename__ = 'tags'
    id            = Column(Integer, primary_key=True)
    tag           = Column(Unicode(255), unique=True, nullable=False)

class EntryTag(Base):
    __tablename__ = 'entrytags'
    entry_id      = Column(Integer, ForeignKey('entries.id'), key='entry', primary_key=True)
    tag_id        = Column(Integer, ForeignKey('tags.id'), key='tag', primary_key=True)

class Entry(Base):
    __tablename__ = 'entries'
    id            = Column(Integer, primary_key=True)
    subject       = Column(Unicode(255), nullable=False)
    # some other fields here
    _tags         = relation('Tag', backref='entries', secondary=EntryTag.__table__)
    tags          = association_proxy('_tags','tag')

これが私がそれを使用しようとしている方法です:

>>> e = db.query(Entry).first()
>>> e.tags
[u'foo']
>>> e.tags = [u'foo', u'bar']  # really this is from a comma-separated input
db.commit()
Traceback (most recent call last):
[...]
sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "tags_tag_key"
 'INSERT INTO tags (id, tag) VALUES (%(id)s, %(tag)s)' {'tag': 'bar', 'id': 11L}
>>> map(lambda t:(t.id,t.tag), db.query(Tag).all())
[(1, u'foo'), (2, u'bar'), (3, u'baz')]

タグu'bar'は ID 2 ですでに存在していました。なぜSQLAlchemyはそれを作成しようとするのではなく、単にそれを添付しなかったのですか? 私のスキーマはどういうわけか間違っていますか?

4

2 に答える 2

3

免責事項:SQLAlchemyを使用してから何年も経っているので、これは何よりも推測です。

多対多のテーブルで挿入を実行するときに、SQLAlchemyが文字列'bar'を魔法のように取得し、それに関連するタグを検索することを期待しているようです。問題のフィールド(「タグ」)は主キーではないため、これは無効だと思います。

タグテーブルが実際にコメントであり、IDとテキストフィールドがある同様の状況を想像してみてください。上記で使用したのと同じe.comments=['u'Foo'、'u'Bar']構文を使用して、エントリにコメントを追加できることが期待されますが、実行するだけでよい場合があります。 INSERT、同じ内容の既存のコメントをチェックしません。

これがおそらくここで行われていることですが、間違ったことを行おうとしていると仮定すると、タグ名の一意性の制約にぶつかって失敗します。

それを修正する方法は?tags.tagを主キーにすることは間違いなく正しいことですが、それがどれほど効率的であるか、SQLAlchemyがそれをどれだけうまく処理するかはわかりません。それができない場合は、エントリに割り当てる前に、名前でタグオブジェクトをクエリしてみてください。Unicode文字列を受け取り、既存のタグを返すか、新しいタグを作成する小さなユーティリティ関数を作成する必要がある場合があります。

于 2009-12-14T10:31:32.717 に答える
0

私はまだ SQLAlchemy 0.5 を使用したことがありません (これを使用した最後のアプリは 0.4 ベースでした) が、コードに 1 つの癖が見られます。association_proxyオブジェクトを変更する必要があります。

次のようなことを試してください:

e.tags.append(u"bar")

それ以外の

e.tags = ...

それでもうまくいかない場合は、それらのテーブルの完全に機能する例を貼り付けてみてください (インポートも含めてください!)。さらにアドバイスをします。

于 2009-12-14T10:37:41.000 に答える