[Sqlalchemy-tickets] Issue #3484: support multiple AbstractConcreteBase branch points in a hierarch
Brought to you by:
zzzeek
|
From: Mike B. <iss...@bi...> - 2015-07-13 18:55:19
|
New issue 3484: support multiple AbstractConcreteBase branch points in a hierarchy https://bitbucket.org/zzzeek/sqlalchemy/issues/3484/support-multiple-abstractconcretebase Mike Bayer: e.g. below, we can query Document or ContactDocument and get a polymorphic query: ``` #!python class Document(AbstractConcreteBase, Base): date = Column(Date) documentType = Column(String) class NotAContact(Document): __tablename__ = 'not_a_contact' id = Column(Integer, primary_key=True) __mapper_args__ = {'polymorphic_identity': 'nc'} class ABCMiddle(object): _sa_abc_base = True @classmethod def _sa_decl_prepare_nocascade(cls): AbstractConcreteBase._sa_decl_prepare_nocascade.__func__(cls) class ContactDocument(ABCMiddle, Document): contactPersonName = Column(String) salesPersonName = Column(String) sendMethod = Column(String) @declared_attr def company_id(self): return Column(ForeignKey('companies.id')) class Offer(ContactDocument): __tablename__ = 'offers' id = Column(Integer, primary_key=True) __mapper_args__ = {'polymorphic_identity': 'offer'} ``` there's an easy patch that *seems* to do this, verify with tests and we can add to 1.0 with "experimental" label ``` #!diff diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index 3d46bd4..7493df3 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -20,7 +20,7 @@ import weakref from .base import _as_declarative, \ _declarative_constructor,\ - _DeferredMapperConfig, _add_attribute + _DeferredMapperConfig, _add_attribute, _get_immediate_cls_attr from .clsregistry import _class_resolver @@ -506,7 +506,8 @@ class AbstractConcreteBase(ConcreteBase): @classmethod def _sa_decl_prepare_nocascade(cls): - if getattr(cls, '__mapper__', None): + if getattr(cls, '__mapper__', None) and \ + not _get_immediate_cls_attr(cls, '_sa_abc_base', strict=True): return to_map = _DeferredMapperConfig.config_for_cls(cls) ``` then the middleware is: ``` #!python class ABCMiddle(object): _sa_abc_base = True @classmethod def _sa_decl_prepare_nocascade(cls): AbstractConcreteBase._sa_decl_prepare_nocascade.__func__(cls) ``` |