SQLAlchemy - 标签字典
我有一个关于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中可以实现吗?
谢谢
2 个回答
-6
简单来说,答案是“不是”。
SQLAlchemy 是一个用来操作 SQL 数据库的工具。
你提到的关系示例其实是把 SQL 表之间的关系转化成一种类似于 Python 字典的结构,这样可以稍微简化一下执行 SQL 查询和在另一个表中找到数据的过程。
这个
item.notes['color'] = Note('color', 'blue')
是非常重要的,因为 Note
是一个独立的表,有两列。你不能把 Note
的部分省略掉。
你必须定义这个其他的 SQL 表,并且你需要创建与这个 SQL 表对应的对象。
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')]
它成功了!! :)