Skip to content

Commit

Permalink
- rework tutorial to be all declarative, all the time
Browse files Browse the repository at this point in the history
- add detail to declarative docs about base classes
  • Loading branch information
zzzeek committed Aug 6, 2011
1 parent e57e148 commit 4abcc0d
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 183 deletions.
375 changes: 205 additions & 170 deletions doc/build/orm/tutorial.rst

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion doc/build/static/docs.css
Expand Up @@ -303,6 +303,10 @@ div.note, div.warning, p.deprecated {
background-color:#EEFFEF;
}

div.topic {
background-color:#D5F0EE;
}

div.admonition, div.topic, p.deprecated {
border:1px solid #CCCCCC;
margin:5px 5px 5px 5px;
Expand All @@ -314,7 +318,7 @@ div.warning .admonition-title {
color:#FF0000;
}

div.admonition .admonition-title {
div.admonition .admonition-title, div.topic .topic-title {
font-weight:bold;
}

Expand Down
2 changes: 1 addition & 1 deletion doc/build/testdocs.py
Expand Up @@ -60,7 +60,7 @@ def replace_file(s, newfile):
raise ValueError("Couldn't find suitable create_engine call to replace '%s' in it" % oldfile)
return s

for filename in ('orm/tutorial', 'core/tutorial',):
for filename in 'orm/tutorial',: # 'core/tutorial',:
filename = '%s.rst' % filename
s = open(filename).read()
#s = replace_file(s, ':memory:')
Expand Down
6 changes: 6 additions & 0 deletions lib/sqlalchemy/engine/__init__.py
Expand Up @@ -130,6 +130,12 @@ def create_engine(*args, **kwargs):
will establish the first actual DBAPI connection when this request
is received. The :func:`.create_engine` call itself does **not**
establish any actual DBAPI connections directly.
See also:
:ref:`engines_toplevel`
:ref:`connections_toplevel`
:param assert_unicode: Deprecated. A warning is raised in all cases when a non-Unicode
object is passed when SQLAlchemy would coerce into an encoding
Expand Down
6 changes: 6 additions & 0 deletions lib/sqlalchemy/engine/base.py
Expand Up @@ -2068,6 +2068,12 @@ class Engine(Connectable, log.Identified):
An :class:`.Engine` object is instantiated publically using the
:func:`~sqlalchemy.create_engine` function.
See also:
:ref:`engines_toplevel`
:ref:`connections_toplevel`
"""

_execution_options = util.immutabledict()
Expand Down
65 changes: 54 additions & 11 deletions lib/sqlalchemy/ext/declarative.py
Expand Up @@ -512,20 +512,32 @@ class Manager(Person):
the creation of the mapper. That recipe is available at
`DeclarativeAbstractConcreteBase <http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DeclarativeAbstractConcreteBase>`_
Mixin Classes
==============
.. _declarative_mixins:
A common need when using :mod:`~sqlalchemy.ext.declarative` is to
share some functionality, often a set of columns, across many
classes. The normal Python idiom would be to put this common code into
a base class and have all the other classes subclass this class.
Mixin and Custom Base Classes
==============================
When using :mod:`~sqlalchemy.ext.declarative`, this need is met by
using a "mixin class". A mixin class is one that isn't mapped to a
table and doesn't subclass the declarative :class:`.Base`. For example::
A common need when using :mod:`~sqlalchemy.ext.declarative` is to
share some functionality, such as a set of common columns, some common
table options, or other mapped properties, across many
classes. The standard Python idioms for this is to have the classes
inherit from a base which includes these common features.
When using :mod:`~sqlalchemy.ext.declarative`, this idiom is allowed
via the usage of a custom declarative base class, as well as a "mixin" class
which is inherited from in addition to the primary base. Declarative
includes several helper features to make this work in terms of how
mappings are declared. An example of some commonly mixed-in
idioms is below::
from sqlalchemy.ext.declarative import declared_attr
class MyMixin(object):
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
__table_args__ = {'mysql_engine': 'InnoDB'}
__mapper_args__= {'always_refresh': True}
Expand All @@ -538,8 +550,39 @@ class MyModel(Base,MyMixin):
name = Column(String(1000))
Where above, the class ``MyModel`` will contain an "id" column
as well as ``__table_args__`` and ``__mapper_args__`` defined
by the ``MyMixin`` mixin class.
as the primary key, a ``__tablename__`` attribute that derives
from the name of the class itself, as well as ``__table_args__``
and ``__mapper_args__`` defined by the ``MyMixin`` mixin class.
Augmenting the Base
~~~~~~~~~~~~~~~~~~~
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::
from sqlalchemy.ext.declarative import declared_attr
class Base(object):
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
__table_args__ = {'mysql_engine': 'InnoDB'}
id = Column(Integer, primary_key=True)
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base(cls=Base)
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.
Mixing in Columns
~~~~~~~~~~~~~~~~~
Expand Down

0 comments on commit 4abcc0d

Please sign in to comment.