To name columns explicitly with a name distinct from their mapped attribute,
just give the column a name. Below, column "some_table_id" is mapped to the
-"id" attribute of `SomeClass`, but in SQL will be represented as "some_table_id"::
+"id" attribute of `SomeClass`, but in SQL will be represented as
+"some_table_id"::
class SomeClass(Base):
__tablename__ = 'some_table'
Note that when the ``__table__`` approach is used, the object is immediately
usable as a plain :class:`.Table` within the class declaration body itself,
as a Python class is only another syntactical block. Below this is illustrated
-by using the ``id`` column in the ``primaryjoin`` condition of a :func:`.relationship`::
+by using the ``id`` column in the ``primaryjoin`` condition of a
+:func:`.relationship`::
class MyClass(Base):
__table__ = Table('my_table', Base.metadata,
primaryjoin=Widget.myclass_id==__table__.c.id)
Similarly, mapped attributes which refer to ``__table__`` can be placed inline,
-as below where we assign the ``name`` column to the attribute ``_name``, generating
-a synonym for ``name``::
+as below where we assign the ``name`` column to the attribute ``_name``,
+generating a synonym for ``name``::
from sqlalchemy.ext.declarative import synonym_for
Declarative makes use of the :func:`~.orm.mapper` function internally
when it creates the mapping to the declared table. The options
-for :func:`~.orm.mapper` are passed directly through via the ``__mapper_args__``
-class attribute. As always, arguments which reference locally
-mapped columns can reference them directly from within the
+for :func:`~.orm.mapper` are passed directly through via the
+``__mapper_args__`` class attribute. As always, arguments which reference
+locally mapped columns can reference them directly from within the
class declaration::
from datetime import datetime
of the intent, especially if the ``start_date`` columns had, for example,
different types. A situation like this can be resolved by using
:class:`.declared_attr` to define the :class:`.Column` conditionally, taking
-care to return the **existing column** via the parent ``__table__`` if it already
-exists::
+care to return the **existing column** via the parent ``__table__`` if it
+already exists::
from sqlalchemy.ext.declarative import declared_attr
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Helper classes provides a simpler pattern for concrete inheritance.
-With these objects, the ``__declare_last__`` helper is used to configure the "polymorphic"
-loader for the mapper after all subclasses have been declared.
+With these objects, the ``__declare_last__`` helper is used to configure the
+"polymorphic" loader for the mapper after all subclasses have been declared.
.. versionadded:: 0.7.3
-An abstract base can be declared using the :class:`.AbstractConcreteBase` class::
+An abstract base can be declared using the
+:class:`.AbstractConcreteBase` class::
from sqlalchemy.ext.declarative import AbstractConcreteBase
In addition to using a pure mixin, most of the techniques in this
section can also be applied to the base class itself, for patterns that
-should apply to all classes derived from a particular base. This
-is achieved using the ``cls`` argument of the :func:`.declarative_base` function::
+should apply to all classes derived from a particular base. This is achieved
+using the ``cls`` argument of the :func:`.declarative_base` function::
from sqlalchemy.ext.declarative import declared_attr
class MyModel(Base):
name = Column(String(1000))
-Where above, ``MyModel`` and all other classes that derive from ``Base`` will have
-a table name derived from the class name, an ``id`` primary key column, as well as
-the "InnoDB" engine for MySQL.
+Where above, ``MyModel`` and all other classes that derive from ``Base`` will
+have a table name derived from the class name, an ``id`` primary key column,
+as well as the "InnoDB" engine for MySQL.
Mixing in Columns
~~~~~~~~~~~~~~~~~
the method without the need to copy it.
.. versionchanged:: > 0.6.5
- Rename 0.6.5 ``sqlalchemy.util.classproperty`` into :class:`~.declared_attr`.
+ Rename 0.6.5 ``sqlalchemy.util.classproperty``
+ into :class:`~.declared_attr`.
Columns generated by :class:`~.declared_attr` can also be
referenced by ``__mapper_args__`` to a limited degree, currently
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mixins can specify user-defined attributes as well as other extension
-units such as :func:`.association_proxy`. The usage of :class:`.declared_attr`
-is required in those cases where the attribute must be tailored specifically
-to the target subclass. An example is when constructing multiple
-:func:`.association_proxy` attributes which each target a different type
-of child object. Below is an :func:`.association_proxy` / mixin example
-which provides a scalar list of string values to an implementing class::
+units such as :func:`.association_proxy`. The usage of
+:class:`.declared_attr` is required in those cases where the attribute must
+be tailored specifically to the target subclass. An example is when
+constructing multiple :func:`.association_proxy` attributes which each
+target a different type of child object. Below is an
+:func:`.association_proxy` / mixin example which provides a scalar list of
+string values to an implementing class::
from sqlalchemy import Column, Integer, ForeignKey, String
from sqlalchemy.orm import relationship
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To define a named, potentially multicolumn :class:`.Index` that applies to all
-tables derived from a mixin, use the "inline" form of :class:`.Index` and establish
-it as part of ``__table_args__``::
+tables derived from a mixin, use the "inline" form of :class:`.Index` and
+establish it as part of ``__table_args__``::
class MyMixin(object):
a = Column(Integer)
~~~~~~~~~~~~~~~~~~~~~~
The ``__declare_last__()`` hook allows definition of
-a class level function that is automatically called by the :meth:`.MapperEvents.after_configured`
-event, which occurs after mappings are assumed to be completed and the 'configure' step
-has finished::
+a class level function that is automatically called by the
+:meth:`.MapperEvents.after_configured` event, which occurs after mappings are
+assumed to be completed and the 'configure' step has finished::
class MyClass(Base):
@classmethod
~~~~~~~~~~~~~~~~~~~
``__abstract__`` causes declarative to skip the production
-of a table or mapper for the class entirely. A class can be added within a hierarchy
-in the same way as mixin (see :ref:`declarative_mixins`), allowing subclasses to extend
-just from the special class::
+of a table or mapper for the class entirely. A class can be added within a
+hierarchy in the same way as mixin (see :ref:`declarative_mixins`), allowing
+subclasses to extend just from the special class::
class SomeAbstractBase(Base):
__abstract__ = True
class MyMappedClass(SomeAbstractBase):
""
-One possible use of ``__abstract__`` is to use a distinct :class:`.MetaData` for different
-bases::
+One possible use of ``__abstract__`` is to use a distinct
+:class:`.MetaData` for different bases::
Base = declarative_base()
__abstract__ = True
metadata = MetaData()
-Above, classes which inherit from ``DefaultBase`` will use one :class:`.MetaData` as the
-registry of tables, and those which inherit from ``OtherBase`` will use a different one.
-The tables themselves can then be created perhaps within distinct databases::
+Above, classes which inherit from ``DefaultBase`` will use one
+:class:`.MetaData` as the registry of tables, and those which inherit from
+``OtherBase`` will use a different one. The tables themselves can then be
+created perhaps within distinct databases::
DefaultBase.metadata.create_all(some_engine)
OtherBase.metadata_create_all(some_other_engine)
cls.metadata = metadata
_as_declarative(cls, cls.__name__, cls.__dict__)
+
def has_inherited_table(cls):
"""Given a class, return True if any of the classes it inherits from has a
mapped table, otherwise return False.
return True
return False
+
class DeclarativeMeta(type):
def __init__(cls, classname, bases, dict_):
if '_decl_class_registry' not in cls.__dict__:
def __setattr__(cls, key, value):
_add_attribute(cls, key, value)
+
def synonym_for(name, map_column=False):
"""Decorator, make a Python @property a query synonym for a column.
return _orm_synonym(name, map_column=map_column, descriptor=fn)
return decorate
+
def comparable_using(comparator_factory):
"""Decorator, allow a Python @property to be used in query criteria.
return comparable_property(comparator_factory, fn)
return decorate
+
class declared_attr(interfaces._MappedAttribute, property):
"""Mark a class-level method as representing the definition of
a mapped property or special declarative member name.
def __get__(desc, self, cls):
return desc.fget(cls)
+
def declarative_base(bind=None, metadata=None, mapper=None, cls=object,
name='Base', constructor=_declarative_constructor,
class_registry=None,
return metaclass(name, bases, class_dict)
+
class ConcreteBase(object):
"""A helper class for 'concrete' declarative mappings.
m._set_with_polymorphic(("*", pjoin))
m._set_polymorphic_on(pjoin.c.type)
+
class AbstractConcreteBase(ConcreteBase):
"""A helper class for 'concrete' declarative mappings.
method is called which first reflects all :class:`.Table`
objects created so far. Classes can define it as such::
- from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
+ from sqlalchemy.ext.declarative import declarative_base
+ from sqlalchemy.ext.declarative import DeferredReflection
Base = declarative_base()
class MyClass(DeferredReflection, Base):
Above, ``MyClass`` is not yet mapped. After a series of
classes have been defined in the above fashion, all tables
- can be reflected and mappings created using :meth:`.DeferredReflection.prepare`::
+ can be reflected and mappings created using
+ :meth:`.DeferredReflection.prepare`::
engine = create_engine("someengine://...")
DeferredReflection.prepare(engine)
from ... import event
from . import clsregistry
+
def _declared_mapping_info(cls):
# deferred mapping
if cls in _MapperConfig.configs:
# in multi-column ColumnProperties.
if key == c.key:
del our_stuff[key]
- declared_columns = sorted(declared_columns, key=lambda c: c._creation_order)
+ declared_columns = sorted(
+ declared_columns, key=lambda c: c._creation_order)
table = None
if hasattr(cls, '__table_cls__'):
if autoload:
table_kw['autoload'] = True
- cls.__table__ = table = table_cls(tablename, cls.metadata,
- *(tuple(declared_columns) + tuple(args)),
- **table_kw)
+ cls.__table__ = table = table_cls(
+ tablename, cls.metadata,
+ *(tuple(declared_columns) + tuple(args)),
+ **table_kw)
else:
table = cls.__table__
if declared_columns:
if not hasattr(cls, '_sa_decl_prepare'):
mt.map()
+
class _MapperConfig(object):
configs = util.OrderedDict()
mapped_table = None
**mapper_args
)
+
def _add_attribute(cls, key, value):
"""add an attribute to an existing declarative class.
cls.__mapper__.add_property(key, value)
elif isinstance(value, MapperProperty):
cls.__mapper__.add_property(
- key,
- clsregistry._deferred_relationship(cls, value)
- )
+ key,
+ clsregistry._deferred_relationship(cls, value)
+ )
else:
type.__setattr__(cls, key, value)
else:
type.__setattr__(cls, key, value)
+
def _declarative_constructor(self, **kwargs):
"""A simple constructor that allows initialization from kwargs.
# themselves when all references to contained classes are removed.
_registries = set()
+
def add_class(classname, cls):
"""Add a class to the _decl_class_registry associated with the
given declarative class.
)
self.contents.add(weakref.ref(item, self._remove_item))
+
class _ModuleMarker(object):
""""refers to a module name within
_decl_class_registry.
on_remove=lambda: self._remove_item(name))
-
class _ModNS(object):
def __init__(self, parent):
self.__parent = parent
raise AttributeError("Module %r has no mapped classes "
"registered under the name %r" % (self.__parent.name, key))
+
class _GetColumns(object):
def __init__(self, cls):
self.cls = cls
" directly to a Column)." % key)
return getattr(self.cls, key)
+
class _GetTable(object):
def __init__(self, key, metadata):
self.key = key
_get_table_key(key, self.key)
]
+
def _determine_container(key, value):
if isinstance(value, _MultipleClassMarker):
value = value.attempt_get([], key)
return _GetColumns(value)
+
def _resolver(cls, prop):
def resolve_arg(arg):
import sqlalchemy
return _GetTable(key, cls.metadata)
elif '_sa_module_registry' in cls._decl_class_registry and \
key in cls._decl_class_registry['_sa_module_registry']:
- return cls._decl_class_registry['_sa_module_registry'].resolve_attr(key)
+ registry = cls._decl_class_registry['_sa_module_registry']
+ return registry.resolve_attr(key)
else:
return fallback[key]
d = util.PopulateDict(access_cls)
+
def return_cls():
try:
x = eval(arg, globals(), d)
return return_cls
return resolve_arg
+
def _deferred_relationship(cls, prop):
if isinstance(prop, RelationshipProperty):