我有一个类,它是SQLAlchemy的声明基的后代。我需要编写一个桥对象,它将在声明基和我正在运行的另一个系统之间进行转换,但我希望桥对象不必确切地知道我记录中的列。在这种情况下,我希望有一种方法来列出记录中的所有列,避免不得不在两个只有模糊关联的地方维护属性列表,同时最小化复制。这意味着我可以创建列属性,然后维护一个单独的列名列表,但是同样,复制也是一个因素--如果我以后想改变这个东西的结构,我必须在这两个地方更改它。
在这种情况下,我考虑将列定义放在dict中,然后遍历dict,使用setattr创建每个列定义,如下所示:
for k,v in self.__column_dict.items():
setattr(self,k,
sqlalchemy.Column(v['column_type'],**v.get('opts',{})),
)
现在,问题是:如果我把这段代码放在类级别上,那么self还没有被定义,并且我得到了一个错误(这是有意义的)。如果我把它放在__init__
中,就会定义self,但是SQLAlchemy的声明基会给出一个错误,因为在类定义完成之前,表上没有主键(这很有意义,因为这些属性直到运行时才会被设置)。
所以,所有的人都说,我如何得到我想要的,而不使用eval,或者说,在这里,我只能使用eval?
编辑:我接受了下面的解决方案,但没有百分之百地使用它(尽管它对我得到答案绝对有帮助)。下面是我最后所做的:(请注意,DeclarativeMeta是sqlalchemy.ext.declarative的一部分,与declarative_base相同)
class MyMeta(DeclarativeMeta):
def __new__(meta, classname, bases, dict_):
klass = type.__new__(meta, classname, bases, dict_)
if dict_.has_key('__classinit__'):
klass.__classinit__ = staticmethod(klass.__classinit__.im_func)
klass.__classinit__(klass, dict_)
return klass
然后,在我的派生类中,
class DerivedClass(declarative_base()):
__tablename__ = 'yaddayadda'
__metaclass__ = MyMeta
def __classinit__(klass, dict_):
klass.__column_dict = <column dict here>
for k,v in klass.__column_dict.items():
setattr(klass,k,
<fancy column stuff>
)
...<rest of class definition>...
发布于 2011-04-20 21:00:01
这可以通过向declarative_base和该元类提供元类来实现。
from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
class MyMeta(DeclarativeMeta):
def __init__(klass, classname, bases, dict_):
for k, v in dict_.items():
if k.endswith('__column_dict'):
for name, datatype, is_pk in v:
setattr(klass, name, Column(name, datatype, primary_key=is_pk))
return DeclarativeMeta.__init__(klass, classname, bases, dict_)
Base = declarative_base(metaclass=MyMeta)
class Bob(Base):
__tablename__ = 'bob'
__column_dict = [('a', Integer, True), ('b', Integer, False)]
bob = Bob()
print bob.a
print bob.b
https://stackoverflow.com/questions/5734301
复制相似问题