首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sqlalchemy动态映射

sqlalchemy动态映射
EN

Stack Overflow用户
提问于 2010-04-04 18:03:19
回答 2查看 16K关注 0票数 13

我有以下问题:

我有这样的课程:

代码语言:javascript
复制
class Word(object):

    def __init__(self):
        self.id = None
        self.columns = {}

    def __str__(self):
        return "(%s, %s)" % (str(self.id), str(self.columns))

self.columns是一个字典,它将保存(columnName:columnValue)值。列的名称在运行时是已知的,并且它们被加载到wordColumns列表中,例如

代码语言:javascript
复制
wordColumns = ['english', 'korean', 'romanian']
代码语言:javascript
复制
wordTable = Table('word', metadata,
                  Column('id', Integer, primary_key = True)
                  )
for columnName in wordColumns:
    wordTable.append_column(Column(columnName, String(255), nullable = False))

我甚至创建了一个显式的映射器属性来“强制”将表列映射到word.columnscolumnName上,而不是word.columnName上,我在映射上没有得到任何错误,但似乎不起作用。

代码语言:javascript
复制
mapperProperties = {}
for column in wordColumns:
    mapperProperties['columns[\'%']' % column] = wordTable.columns[column]

mapper(Word, wordTable, mapperProperties)

当我加载一个word对象时,SQLAlchemy创建了一个具有word.column‘’english‘,word.column’‘korean’等属性的对象,而不是将它们加载到word.columns字典中。因此,它为每一列创建一个新属性。此外,word.columns字典甚至都不存在。

同样,当我试图持久化一个单词时,SQLAlchemy希望在名为word.columns'english'的属性中找到列值,而不是在字典word.columns中。

我不得不说,我使用Python和SQLAlchemy的经验非常有限,也许我不可能做到我想要做的事情。

感谢您的任何帮助,

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-04-05 00:07:09

似乎您可以直接使用属性,而不是使用columns dict

考虑以下设置:

代码语言:javascript
复制
from sqlalchemy import Table, Column, Integer, Unicode, MetaData, create_engine
from sqlalchemy.orm import mapper, create_session

class Word(object):
    pass

wordColumns = ['english', 'korean', 'romanian']
e = create_engine('sqlite://')
metadata = MetaData(bind=e)

t = Table('words', metadata, Column('id', Integer, primary_key=True),
    *(Column(wordCol, Unicode(255)) for wordCol in wordColumns))
metadata.create_all()
mapper(Word, t)
session = create_session(bind=e, autocommit=False, autoflush=True)

使用该空类,您可以执行以下操作:

代码语言:javascript
复制
w = Word()
w.english = u'name'
w.korean = u'이름'
w.romanian = u'nume'

session.add(w)
session.commit()

当你想要访问数据的时候:

代码语言:javascript
复制
w = session.query(Word).filter_by(english=u'name').one()
print w.romanian

这就是whole ORM点**,您可以在自己的类上使用类似属性的访问,而不是使用tupledict来访问数据。

所以我想知道你为什么想要使用dict。也许是因为您有包含语言名称的字符串。为此,您可以使用python的getattrsetattr,就像您对任何python对象所做的那样:

代码语言:javascript
复制
language = 'korean'
print getattr(w, language)

这应该会解决你所有的问题。

也就是说,如果您仍然希望使用dict-like访问列,也是可以的。您只需实现一个dict-like对象。我现在会提供代码来做这件事,尽管我认为这绝对是不必要的杂乱,因为属性访问是如此干净。如果您的问题已经通过使用上面的方法解决了,那么不要使用下面的代码。

您可以在Word类上执行此操作:

代码语言:javascript
复制
class Word(object):
    def __getitem__(self, item): 
        return getattr(self, item)
    def __setitem__(self, item, value):
        return setattr(self, item, value)

设置的其余部分工作方式与上面相同。然后你可以像这样使用它:

代码语言:javascript
复制
w = Word()
w['english'] = u'name'

如果需要columns属性,则需要dict-like

代码语言:javascript
复制
class AttributeDict(DictMixin):
    def __init__(self, obj):
        self._obj = obj
    def __getitem__(self, item):
        return getattr(self._obj, item)
    def __setitem__(self, item, value):
        return setattr(self._obj, item, value)

class Word(object):
    def __init__(self):
        self.columns = AttributeDict(self)

然后,您可以按预期使用:

代码语言:javascript
复制
w = Word()
w.columns['english'] = u'name' 

我想您会同意,所有这些都是不必要的复杂,没有额外的好处。

票数 33
EN

Stack Overflow用户

发布于 2012-02-06 15:12:51

我使用了nosklo的解决方案(谢谢!)但是我在列行(csv的第一行)中已经有了一个主键(作为pk_col传入)。所以我想我应该分享我的修改。我用了一个三元组。

代码语言:javascript
复制
table = Table(tablename, metadata,
    *((Column(pk_col, Integer, primary_key=True)) if rowname == pk_col else (Column(rowname, String())) for rowname in row.keys()))
table.create()
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2574105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档