[英]sqlalchemy dynamic mapping
我有以下问题:
我上课了:
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是一个dict,它将保存(columnName:columnValue)值。 列的名称在运行时是已知的,例如,它们被加载到wordColumns列表中
wordColumns = ['english', 'korean', 'romanian']
wordTable = Table('word', metadata,
Column('id', Integer, primary_key = True)
)
for columnName in wordColumns:
wordTable.append_column(Column(columnName, String(255), nullable = False))
我甚至创建了一个显式映射器属性来“强制”表格列映射到word.columns [columnName],而不是word.columnName,我没有得到任何映射错误,但它似乎不起作用。
mapperProperties = {}
for column in wordColumns:
mapperProperties['columns[\'%']' % column] = wordTable.columns[column]
mapper(Word, wordTable, mapperProperties)
当我加载一个单词对象时,SQLAlchemy创建一个具有word.columns ['english'],word.columns ['korean']等属性的对象,而不是将它们加载到word.columns dict中。 因此,对于每个列,它会创建一个新属性。 而且word.columns字典甚至不存在。
同样,当我尝试坚持一个单词时,SQLAlchemy希望在名为word.columns ['english'](字符串类型)的属性中找到列值,而不是字典word.columns。
我不得不说我对Python和SQLAlchemy的经验非常有限,也许我不可能做我想做的事情。
任何帮助,赞赏,
提前致谢。
您似乎可以直接使用属性而不是使用columns
dict
。
请考虑以下设置:
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)
有了这个空课,你可以做:
w = Word()
w.english = u'name'
w.korean = u'이름'
w.romanian = u'nume'
session.add(w)
session.commit()
当您想要访问数据时:
w = session.query(Word).filter_by(english=u'name').one()
print w.romanian
这是整个sqlalchemy
的ORM点 ,而不是使用tuple
或dict
来访问数据,您在自己的类上使用类似属性的访问。
所以我想知道你想使用dict
。 也许是因为你有语言名字的字符串。 那么,你可以使用python的getattr
和setattr
,就像你在任何python对象上一样:
language = 'korean'
print getattr(w, language)
这应该可以解决您的所有问题。
也就是说,如果你仍然希望使用dict
的访问列,那么它也是可能的。 你只需要实现一个类似dict
的对象。 我现在将提供代码来执行此操作,即使我认为这绝对是不必要的混乱,因为属性访问是如此干净。 如果您的问题已通过上述方法解决,请不要使用此点下方的代码。
你可以在Word
类上做到这一点:
class Word(object):
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
其余设置如上所述。 然后你可以像这样使用它:
w = Word()
w['english'] = u'name'
如果你想要一个columns
属性,那么你需要一个类似dict
的
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)
然后你可以按照你的意图使用:
w = Word()
w.columns['english'] = u'name'
我想你会同意所有这些都是不必要的复杂,没有额外的好处。
我使用了nosklo的解决方案(谢谢!)但是我已经在列行(csv的第一行)中有一个主键(以pk_col传入)。 所以我想我会分享我的修改。 我使用了三元组。
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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.