2

SQLAlchemy でのエンティティのマッピングに関して質問があります。

一部の永続オブジェクトへの外部キーが既に含まれている一時オブジェクトがあります。SQLAlchemy が参照されたオブジェクトをフェッチし、それらを関係属性に割り当てることを望みます。SQLAlchemy のドキュメントから、これを実現するには、セッションでマージ操作を使用する必要があると考えました。しかし、私の構成では、うまくいきません。

これは私の問題を示す最小限の例です:

# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy.orm import mapper
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker

class User(object):
    def __init__(self, id, name, fullname, password, best_friend_id=None):
        self.id = id
        self.name = name
        self.fullname = fullname
        self.password = password
        self.best_friend_id = best_friend_id

    def __repr__(self):
        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)


class Dog(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)

engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
metadata = MetaData()

dogs_table = Table('dogs', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
)


users_table = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
    Column('fullname', String),
    Column('password', String),
    Column('best_friend_id', Integer, ForeignKey('dogs.id'))
)

metadata.create_all(engine)
mapper(User, users_table, properties={'best_friend': relationship(Dog, uselist=False)})
mapper(Dog, dogs_table)

dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret', best_friend_id=1)

session.add(dog)
session.commit()

merged_lordling = session.merge(lordling)
print str(merged_lordling.best_friend.name)

merged_lordling.best_friend犬の「ハッソ」が入っていると思います。しかし、それはまだNoneです。

4

1 に答える 1

1

私は最近、この同じ問題に悩まされていました。リレーションシップを確立したら、外部キーを明示的に使用するのではなく、Dogインスタンスを直接割り当てるだけです。User.best_friend正確な理由はわかりませんが、同様の問題を調査しているときに、そうすると、関連するすべてのインスタンスをフラッシュするまで、SQLAlchemy は関係プロパティを設定しないことに気付きました。

したがって、代わりに:

dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret', 
                best_friend_id=1)

session.add(dog)

単に行う:

dog = Dog(id=1, name='Hasso')
lordling = User(id=2, name='John', fullname='Miller', password='very_secret', 
                best_friend=dog)

session.add(lordling)

あるいは:

lordling = User(id=2, name='John', fullname='Miller', password='very_secret', 
                best_friend=Dog(id=1, name='Hasso'))
session.add(lordling)    

原則として、関係が確立されている場合は、外部キー列を直接使用することは避けてください。ORM を採用し、他に選択肢がない場合にのみ、外部キーから直接割り当てまたはクエリを実行します。私はそれを難し​​い方法で学びました。

于 2013-11-08T23:18:27.833 に答える