2016-09-23 55 views
0

我有許多具有相同列的表。不同之處在於表名本身。我想設置一個繼承鏈來最小化代碼重複。下面的單層繼承的作品我希望它的方式:在sqlalchemy聲明基礎中使用多級繼承

from sqlalchemy import Column, Integer, Text 
from sqlalchemy.ext.declarative import declarative_base, declared_attr 
from sqlalchemy.orm import sessionmaker 

engine = sqlalchemy.create_engine('sqlite:///monDom5.db') 


class Base(object): 
    """base for all table classes""" 
    __abstract__ = True 
    __table_args__ = {'autoload': True, 'autoload_with': engine} 
    @declared_attr 
    def __tablename__(cls): 
     return cls.__name__.lower() 


Base = declarative_base(cls=Base) 


class TransMap_HgmIntronVector(Base): 
    AlignmentId = Column(Text, primary_key=True) 

,但需要我爲Hgm基地的每個實例指定AlignmentId列。我反而想做到這一點,卻得到了一個sqlalchemy.exc.InvalidRequestError當我嘗試實際使用它:

from sqlalchemy import Column, Integer, Text 
from sqlalchemy.ext.declarative import declarative_base, declared_attr 
from sqlalchemy.orm import sessionmaker 

engine = sqlalchemy.create_engine('sqlite:///monDom5.db') 

class Base(object): 
    """base for all table classes""" 
    __abstract__ = True 
    __table_args__ = {'autoload': True, 'autoload_with': engine} 
    @declared_attr 
    def __tablename__(cls): 
     return cls.__name__.lower() 


# model for all Hgm tables 

class Hgm(Base): 
    __abstract__ = True 
    AlignmentId = Column(Text, primary_key=True) 


Base = declarative_base(cls=Hgm) 

class TransMap_HgmIntronVector(Hgm): 
    pass 



metadata = Base.metadata 
Session = sessionmaker(bind=engine) 
session = Session() 

導致錯誤

>>> metadata = Base.metadata 
>>> Session = sessionmaker(bind=engine) 
>>> session = Session() 
>>> session.query(TransMap_HgmIntronVector).all() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1260, in query 
    return self._query_cls(entities, self, **kwargs) 
    File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 110, in __init__ 
    self._set_entities(entities) 
    File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 118, in _set_entities 
    entity_wrapper(self, ent) 
    File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 3829, in __init__ 
    "expected - got '%r'" % (column,) 
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<class '__main__.TransMap_HgmIntronVector'>' 
+0

你實際上是否打算使用sqlite?或另一個數據庫(一些支持不同類型的繼承)? –

+0

數據庫實際上是sqlite。 –

回答

1

一個例子是在docs。特別是,__abstract__ = True是沒有必要的。這工作正常:

class Base(object): 
    @declared_attr 
    def __tablename__(cls): 
     return cls.__name__.lower() 

class Hgm(Base): 
    AlignmentId = Column(Text, primary_key=True) 

Base = declarative_base(cls=Hgm) 

class TransMap_HgmIntronVector(Base): 
    pass 

請注意,它可能會更簡單,只需使用mixin爲相同的列代替。

+0

就我所知,文檔中沒有任何示例可以解決此問題。刪除'__abstract__'不能解決問題。使用mixin可能會有所幫助。 –

+0

@IanFiddes這是因爲你從'Hgm'而不是'Base'派生了'TransMap_HgmIntronVector'。 – univerio