16

SQLAlchemy について質問があります。マップされたクラスに辞書のような属性を追加するにはどうすればよいですか。これは、文字列キーを文字列値にマップし、データベース (元のマップされたオブジェクトと同じまたは別のテーブル) に格納されます。これにより、オブジェクトの任意のタグのサポートが追加されます。

SQLAlchemy のドキュメントで次の例を見つけました。

from sqlalchemy.orm.collections import column_mapped_collection, attribute_mapped_collection, mapped_collection

mapper(Item, items_table, properties={
# key by column
'notes': relation(Note, collection_class=column_mapped_collection(notes_table.c.keyword)),
# or named attribute
'notes2': relation(Note, collection_class=attribute_mapped_collection('keyword')),
# or any callable
'notes3': relation(Note, collection_class=mapped_collection(lambda entity: entity.a + entity.b))
})

item = Item()
item.notes['color'] = Note('color', 'blue')

しかし、次の動作が必要です。

mapper(Item, items_table, properties={
# key by column
'notes': relation(...),
})

item = Item()
item.notes['color'] = 'blue'

SQLAlchemyで可能ですか?

ありがとうございました

4

2 に答える 2

22

簡単な答えはイエスです。

アソシエーション プロキシを使用するだけです。

from sqlalchemy import Column, Integer, String, Table, create_engine
from sqlalchemy import orm, MetaData, Column, ForeignKey
from sqlalchemy.orm import relation, mapper, sessionmaker
from sqlalchemy.orm.collections import column_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy

テスト環境を作成します。

engine = create_engine('sqlite:///:memory:', echo=True)
meta = MetaData(bind=engine)

テーブルを定義します。

tb_items = Table('items', meta, 
        Column('id', Integer, primary_key=True), 
        Column('name', String(20)),
        Column('description', String(100)),
    )
tb_notes = Table('notes', meta, 
        Column('id_item', Integer, ForeignKey('items.id'), primary_key=True),
        Column('name', String(20), primary_key=True),
        Column('value', String(100)),
    )
meta.create_all()

クラス (クラスの に注意してくださいassociation_proxy):

class Note(object):
    def __init__(self, name, value):
        self.name = name
        self.value = value
class Item(object):
    def __init__(self, name, description=''):
        self.name = name
        self.description = description
    notes = association_proxy('_notesdict', 'value', creator=Note)

マッピング:

mapper(Note, tb_notes)
mapper(Item, tb_items, properties={
        '_notesdict': relation(Note, 
             collection_class=column_mapped_collection(tb_notes.c.name)),
    })

次に、それをテストします。

Session = sessionmaker(bind=engine)
s = Session()

i = Item('ball', 'A round full ball')
i.notes['color'] = 'orange'
i.notes['size'] = 'big'
i.notes['data'] = 'none'

s.add(i)
s.commit()
print i.notes

それは印刷します:

{u'color': u'orange', u'data': u'none', u'size': u'big'}

しかし、それらはメモ表にありますか?

>>> print list(tb_notes.select().execute())
[(1, u'color', u'orange'), (1, u'data', u'none'), (1, u'size', u'big')]

できます!!:)

于 2009-04-24T00:21:28.013 に答える
-6

簡単な答えは「いいえ」です。

SQLAlchemy は、SQL データベースのラッパーです。

引用したリレーションの例では、SQL テーブル間のリレーションシップを Python マップのような構造に変換して、SQL SELECT ステートメントの実行と別のテーブルの行の検索を少し簡単にしています。

item.notes['color'] = Note('color', 'blue')

Noteは2 つの列を持つ個別のテーブルであるため、必須です。その部分を残すことはできませんNote

この別の SQL テーブルを定義し、その SQL テーブルにマップされるオブジェクトを作成する必要があります。

于 2009-04-23T10:25:39.830 に答える