diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-02-11 19:55:34 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-02-11 19:55:34 -0500 |
| commit | 4a79bc578c67297c707a00d8fafaba533e2833d9 (patch) | |
| tree | 808a412724a8137a95472ba974def1073ea1a301 /lib/sqlalchemy/ext/declarative | |
| parent | 0050a8d3db04767b97e48f3aa71381b786481231 (diff) | |
| download | sqlalchemy-4a79bc578c67297c707a00d8fafaba533e2833d9.tar.gz | |
- Fixed bug where :class:`.AbstractConcreteBase` would fail to be
fully usable within declarative relationship configuration, as its
string classname would not be available in the registry of classnames
at mapper configuration time. The class now explicitly adds itself
to the class regsitry, and additionally both :class:`.AbstractConcreteBase`
as well as :class:`.ConcreteBase` set themselves up *before* mappers
are configured within the :func:`.configure_mappers` setup, using
the new :meth:`.MapperEvents.before_configured` event. [ticket:2950]
- Added new :meth:`.MapperEvents.before_configured` event which allows
an event at the start of :func:`.configure_mappers`, as well
as ``__declare_first__()`` hook within declarative to complement
``__declare_last__()``.
- modified how after_configured is invoked; we just make a dispatch()
not actually connected to any mapper. this makes it easier
to also invoke before_configured correctly.
- improved the ComparableEntity fixture to handle collections that are sets.
Diffstat (limited to 'lib/sqlalchemy/ext/declarative')
| -rw-r--r-- | lib/sqlalchemy/ext/declarative/__init__.py | 36 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/declarative/api.py | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/declarative/base.py | 4 |
3 files changed, 43 insertions, 4 deletions
diff --git a/lib/sqlalchemy/ext/declarative/__init__.py b/lib/sqlalchemy/ext/declarative/__init__.py index e878e362d..ebd613093 100644 --- a/lib/sqlalchemy/ext/declarative/__init__.py +++ b/lib/sqlalchemy/ext/declarative/__init__.py @@ -656,7 +656,7 @@ Using the Concrete Helpers ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Helper classes provides a simpler pattern for concrete inheritance. -With these objects, the ``__declare_last__`` helper is used to configure the +With these objects, the ``__declare_first__`` helper is used to configure the "polymorphic" loader for the mapper after all subclasses have been declared. .. versionadded:: 0.7.3 @@ -702,6 +702,26 @@ Either ``Employee`` base can be used in the normal fashion:: 'concrete':True} +The :class:`.AbstractConcreteBase` class is itself mapped, and can be +used as a target of relationships:: + + class Company(Base): + __tablename__ = 'company' + + id = Column(Integer, primary_key=True) + employees = relationship("Employee", + primaryjoin="Company.id == Employee.company_id") + + +.. versionchanged:: 0.9.3 Support for use of :class:`.AbstractConcreteBase` + as the target of a :func:`.relationship` has been improved. + +It can also be queried directly:: + + for employee in session.query(Employee).filter(Employee.name == 'qbert'): + print(employee) + + .. _declarative_mixins: Mixin and Custom Base Classes @@ -1192,6 +1212,20 @@ assumed to be completed and the 'configure' step has finished:: .. versionadded:: 0.7.3 +``__declare_first__()`` +~~~~~~~~~~~~~~~~~~~~~~ + +Like ``__declare_last__()``, but is called at the beginning of mapper configuration +via the :meth:`.MapperEvents.before_configured` event:: + + class MyClass(Base): + @classmethod + def __declare_first__(cls): + "" + # do something before mappings are configured + +.. versionadded:: 0.9.3 + .. _declarative_abstract: ``__abstract__`` diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index 2418c6e50..84b97f629 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -20,7 +20,7 @@ from .base import _as_declarative, \ _declarative_constructor,\ _DeferredMapperConfig, _add_attribute from .clsregistry import _class_resolver - +from . import clsregistry def instrument_declarative(cls, registry, metadata): """Given a class, configure the class declaratively, @@ -325,7 +325,7 @@ class ConcreteBase(object): ), 'type', 'pjoin') @classmethod - def __declare_last__(cls): + def __declare_first__(cls): m = cls.__mapper__ if m.with_polymorphic: return @@ -370,10 +370,11 @@ class AbstractConcreteBase(ConcreteBase): __abstract__ = True @classmethod - def __declare_last__(cls): + def __declare_first__(cls): if hasattr(cls, '__mapper__'): return + clsregistry.add_class(cls.__name__, cls) # can't rely on 'self_and_descendants' here # since technically an immediate subclass # might not be mapped, but a subclass diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index 4fda9c734..eb66f12b6 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -52,6 +52,10 @@ def _as_declarative(cls, classname, dict_): @event.listens_for(mapper, "after_configured") def go(): cls.__declare_last__() + if '__declare_first__' in base.__dict__: + @event.listens_for(mapper, "before_configured") + def go(): + cls.__declare_first__() if '__abstract__' in base.__dict__: if (base is cls or (base in cls.__bases__ and not _is_declarative_inherits) |
