为SQLAlchemy多个数据库设置关系/映射

2024-04-24 04:21:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我是SQLAlchemy和关系数据库的新手,我正在尝试为带注释的词典建立一个模型。我想为可以在运行时添加或删除的单词支持任意数量的键值注释。由于键的名称中会有很多重复,所以我不想直接使用this solution,尽管代码是相似的。在

我的设计有word对象和property对象。单词和属性存储在单独的表中,表中有一个链接两者的属性值表。代码如下:

from sqlalchemy import Column, Integer, String, Table, create_engine
from sqlalchemy import MetaData, ForeignKey
from sqlalchemy.orm import relation, mapper, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///test.db', echo=True)
meta = MetaData(bind=engine)

property_values = Table('property_values', meta,
    Column('word_id', Integer, ForeignKey('words.id')),
    Column('property_id', Integer, ForeignKey('properties.id')),
    Column('value', String(20))
)
words = Table('words', meta,
    Column('id', Integer, primary_key=True),
    Column('name', String(20)),
    Column('freq', Integer)
)
properties = Table('properties', meta,
    Column('id', Integer, primary_key=True),
    Column('name', String(20), nullable=False, unique=True)
)
meta.create_all()

class Word(object):
    def __init__(self, name, freq=1):
        self.name = name
        self.freq = freq

class Property(object):
    def __init__(self, name):
        self.name = name
mapper(Property, properties)  

现在我想做的是:

^{pr2}$

理想情况下,这应该将1|foo|42添加到words表中,将1|bar添加到properties表中,并将1|1|yes添加到property}值表中。但是,我没有合适的映射和关系来实现这一点。我从阅读http://www.sqlalchemy.org/docs/05/mappers.html#association-pattern上的文档中得到一种感觉,我想在这里使用一个关联代理或类似的东西,但是语法不清楚。我做了这样的实验:

mapper(Word, words, properties={
    'properties': relation(Property, secondary=property_values)
    })

但是这个映射器只填充外键值,我还需要填充另一个值。如有任何帮助,我们将不胜感激。在


Tags: namefromimportselfidstringsqlalchemytable
3条回答

只需使用Dictionary-Based Collections mapping映射-开箱即用的解决方案。从链接中提取:

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')
print item.notes['color']

或者尝试Inserting data in Many to Many relationship in SQLAlchemy的解决方案。显然,您必须用dict替换list逻辑。
问问题作者用associationproxy发布hist的最终代码,他在最后提到了他使用的代码。在

布伦特评论,以上:

您可以使用session.flush()而不是commit()来获得模型实例上的idflush()将执行必要的SQL,但不会提交,因此您可以稍后根据需要回滚。在

存在{a1},界面略有差异。但是通过定义__getitem____setitem__和{}方法很容易解决这个问题。在

相关问题 更多 >