From: Mike Bayer Date: Mon, 8 Dec 2008 20:21:02 +0000 (+0000) Subject: - removed redundant declarative docs X-Git-Tag: rel_0_5_0~126 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=082d5db64f85828f219b6c4321208f1b093a02ce;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - removed redundant declarative docs - cleanup of metadata/foreignkey docs --- diff --git a/doc/build/conf.py b/doc/build/conf.py index c9f56f96e3..20317a1164 100644 --- a/doc/build/conf.py +++ b/doc/build/conf.py @@ -184,7 +184,8 @@ latex_documents = [ #latex_use_parts = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# sets TOC depth to 2. +latex_preamble = '\setcounter{tocdepth}{2}' # Documents to append as an appendix to all manuals. #latex_appendices = [] diff --git a/doc/build/mappers.rst b/doc/build/mappers.rst index d1cac47042..80fe8045a2 100644 --- a/doc/build/mappers.rst +++ b/doc/build/mappers.rst @@ -160,6 +160,8 @@ Validators also receive collection events, when items are added to a collection: def validate_address(self, key, address): assert '@' in address.email return address + +.. _synonyms: Using Descriptors ~~~~~~~~~~~~~~~~~~ diff --git a/doc/build/metadata.rst b/doc/build/metadata.rst index 9bc22f7867..b4da3c4afa 100644 --- a/doc/build/metadata.rst +++ b/doc/build/metadata.rst @@ -33,6 +33,11 @@ To represent a Table, use the ``Table`` class:: The specific datatypes for each Column, such as Integer, String, etc. are described in `types`, and exist within the module ``sqlalchemy.types`` as well as the global ``sqlalchemy`` namespace. +.. _metadata_foreignkeys: + +Defining Foreign Keys +--------------------- + Foreign keys are most easily specified by the ``ForeignKey`` object within a ``Column`` object. For a composite foreign key, i.e. a foreign key that contains multiple columns referencing multiple columns to a composite primary key, an explicit syntax is provided which allows the correct table CREATE statements to be generated:: # a table with a composite primary key @@ -53,6 +58,9 @@ Foreign keys are most easily specified by the ``ForeignKey`` object within a ``C Above, the ``invoice_items`` table will have ``ForeignKey`` objects automatically added to the ``invoice_id`` and ``ref_num`` ``Column`` objects as a result of the additional ``ForeignKeyConstraint`` object. +Accessing Tables and Columns +---------------------------- + The ``MetaData`` object supports some handy methods, such as getting a list of Tables in the order (or reverse) of their dependency:: >>> for t in metadata.table_iterator(reverse=False): diff --git a/doc/build/reference/ext/declarative.rst b/doc/build/reference/ext/declarative.rst index ac6295d7b7..81c713df72 100644 --- a/doc/build/reference/ext/declarative.rst +++ b/doc/build/reference/ext/declarative.rst @@ -1,252 +1,5 @@ declarative =========== -:author: Mike Bayer -:version: 0.4.4 or greater - -``declarative`` intends to be a fully featured replacement for the very old ``activemapper`` extension. Its goal is to redefine the organization of class, ``Table``, and ``mapper()`` constructs such that they can all be defined "at once" underneath a class declaration. Unlike ``activemapper``, it does not redefine normal SQLAlchemy configurational semantics - regular ``Column``, ``relation()`` and other schema or ORM constructs are used in almost all cases. - -``declarative`` is a so-called "micro declarative layer"; it does not generate table or column names and requires almost as fully verbose a configuration as that of straight tables and mappers. As an alternative, the `Elixir `_ project is a full community-supported declarative layer for SQLAlchemy, and is recommended for its active-record-like semantics, its convention-based configuration, and plugin capabilities. - -SQLAlchemy object-relational configuration involves the usage of Table, mapper(), and class objects to define the three areas of configuration. -declarative moves these three types of configuration underneath the individual mapped class. Regular SQLAlchemy schema and ORM constructs are used -in most cases: - -.. sourcecode:: python+sql - - from sqlalchemy.ext.declarative import declarative_base - - Base = declarative_base() - - class SomeClass(Base): - __tablename__ = 'some_table' - id = Column('id', Integer, primary_key=True) - name = Column('name', String(50)) - -Above, the ``declarative_base`` callable produces a new base class from which all mapped classes inherit from. When the class definition is -completed, a new ``Table`` and ``mapper()`` have been generated, accessible via the ``__table__`` and ``__mapper__`` attributes on the -``SomeClass`` class. - -You may omit the names from the Column definitions. Declarative will fill -them in for you: - -.. sourcecode:: python+sql - - class SomeClass(Base): - __tablename__ = 'some_table' - id = Column(Integer, primary_key=True) - name = Column(String(50)) - -Attributes may be added to the class after its construction, and they will be added to the underlying ``Table`` and ``mapper()`` definitions as -appropriate: - -.. sourcecode:: python+sql - - SomeClass.data = Column('data', Unicode) - SomeClass.related = relation(RelatedInfo) - -Classes which are mapped explicitly using ``mapper()`` can interact freely with declarative classes. - -The ``declarative_base`` base class contains a ``MetaData`` object where newly defined ``Table`` objects are collected. This is accessed via the ````metadata```` class level accessor, so to create tables we can say: - -.. sourcecode:: python+sql - - engine = create_engine('sqlite://') - Base.metadata.create_all(engine) - -The ``Engine`` created above may also be directly associated with the declarative base class using the ``bind`` keyword argument, where it will be associated with the underlying ``MetaData`` object and allow SQL operations involving that metadata and its tables to make use of that engine automatically: - -.. sourcecode:: python+sql - - Base = declarative_base(bind=create_engine('sqlite://')) - -Or, as ``MetaData`` allows, at any time using the ``bind`` attribute: - -.. sourcecode:: python+sql - - Base.metadata.bind = create_engine('sqlite://') - -The ``declarative_base`` can also receive a pre-created ``MetaData`` object, which allows a declarative setup to be associated with an already existing traditional collection of ``Table`` objects: - -.. sourcecode:: python+sql - - mymetadata = MetaData() - Base = declarative_base(metadata=mymetadata) - -Relations to other classes are done in the usual way, with the added feature that the class specified to ``relation()`` may be a string name. The -"class registry" associated with ``Base`` is used at mapper compilation time to resolve the name into the actual class object, which is expected to -have been defined once the mapper configuration is used: - -.. sourcecode:: python+sql - - class User(Base): - __tablename__ = 'users' - - id = Column('id', Integer, primary_key=True) - name = Column('name', String(50)) - addresses = relation("Address", backref="user") - - class Address(Base): - __tablename__ = 'addresses' - - id = Column('id', Integer, primary_key=True) - email = Column('email', String(50)) - user_id = Column('user_id', Integer, ForeignKey('users.id')) - -Column constructs, since they are just that, are immediately usable, as below where we define a primary join condition on the ``Address`` class -using them: - -.. sourcecode:: python+sql - - class Address(Base) - __tablename__ = 'addresses' - - id = Column('id', Integer, primary_key=True) - email = Column('email', String(50)) - user_id = Column('user_id', Integer, ForeignKey('users.id')) - user = relation(User, primaryjoin=user_id==User.id) - -In addition to the main argument for ``relation``, other arguments -which depend upon the columns present on an as-yet undefined class -may also be specified as strings. These strings are evaluated as -Python expressions. The full namespace available within this -evaluation includes all classes mapped for this declarative base, -as well as the contents of the ``sqlalchemy`` package, including -expression functions like ``desc`` and ``func``: - -.. sourcecode:: python+sql - - class User(Base): - # .... - addresses = relation("Address", order_by="desc(Address.email)", - primaryjoin="Address.user_id==User.id") - -As an alternative to string-based attributes, attributes may also be -defined after all classes have been created. Just add them to the target -class after the fact: - -.. sourcecode:: python+sql - - User.addresses = relation(Address, primaryjoin=Address.user_id==User.id) - -Synonyms are one area where ``declarative`` needs to slightly change the usual SQLAlchemy configurational syntax. To define a -getter/setter which proxies to an underlying attribute, use ``synonym`` with the ``descriptor`` argument: - -.. sourcecode:: python+sql - - class MyClass(Base): - __tablename__ = 'sometable' - - _attr = Column('attr', String) - - def _get_attr(self): - return self._some_attr - def _set_attr(self, attr): - self._some_attr = attr - attr = synonym('_attr', descriptor=property(_get_attr, _set_attr)) - -The above synonym is then usable as an instance attribute as well as a class-level expression construct: - -.. sourcecode:: python+sql - - x = MyClass() - x.attr = "some value" - session.query(MyClass).filter(MyClass.attr == 'some other value').all() - -The ``synonym_for`` decorator can accomplish the same task: - -.. sourcecode:: python+sql - - class MyClass(Base): - __tablename__ = 'sometable' - - _attr = Column('attr', String) - - @synonym_for('_attr') - @property - def attr(self): - return self._some_attr - -Similarly, ``comparable_using`` is a front end for the ``comparable_property`` ORM function: - -.. sourcecode:: python+sql - - class MyClass(Base): - __tablename__ = 'sometable' - - name = Column('name', String) - - @comparable_using(MyUpperCaseComparator) - @property - def uc_name(self): - return self.name.upper() - -As an alternative to ``__tablename__``, a direct ``Table`` construct may be used. The ``Column`` objects, which in this case require their names, will be added to the mapping just like a regular mapping to a table: - -.. sourcecode:: python+sql - - class MyClass(Base): - __table__ = Table('my_table', Base.metadata, - Column('id', Integer, primary_key=True), - Column('name', String(50)) - ) - -Other table-based attributes include ``__table_args__``, which is -either a dictionary as in: - -.. sourcecode:: python+sql - - class MyClass(Base) - __tablename__ = 'sometable' - __table_args__ = {'mysql_engine':'InnoDB'} - -or a dictionary-containing tuple in the form -``(arg1, arg2, ..., {kwarg1:value, ...})``, as in: - -.. sourcecode:: python+sql - - class MyClass(Base) - __tablename__ = 'sometable' - __table_args__ = (ForeignKeyConstraint(['id'], ['remote_table.id']), {'autoload':True}) - -Mapper arguments are specified using the ``__mapper_args__`` class variable. Note that the column objects declared on the class are immediately -usable, as in this joined-table inheritance example: - -.. sourcecode:: python+sql - - class Person(Base): - __tablename__ = 'people' - id = Column('id', Integer, primary_key=True) - discriminator = Column('type', String(50)) - __mapper_args__ = {'polymorphic_on':discriminator} - - class Engineer(Person): - __tablename__ = 'engineers' - __mapper_args__ = {'polymorphic_identity':'engineer'} - id = Column('id', Integer, ForeignKey('people.id'), primary_key=True) - primary_language = Column('primary_language', String(50)) - -For single-table inheritance, the ``__tablename__`` and ``__table__`` class variables are optional on a class when the class inherits from another -mapped class. - -As a convenience feature, the ``declarative_base()`` sets a default constructor on classes which takes keyword arguments, and assigns them to the -named attributes: - -.. sourcecode:: python+sql - - e = Engineer(primary_language='python') - -Note that ``declarative`` has no integration built in with sessions, and is only intended as an optional syntax for the regular usage of mappers -and Table objects. A typical application setup using ``scoped_session`` might look like: - -.. sourcecode:: python+sql - - engine = create_engine('postgres://scott:tiger@localhost/test') - Session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) - Base = declarative_base() - -Mapped instances then make usage of ``Session`` in the usual way. - .. automodule:: sqlalchemy.ext.declarative - :members: - :undoc-members: + :members: \ No newline at end of file diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 37fa98d78f..50f8f24e60 100644 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -1,8 +1,11 @@ """A simple declarative layer for SQLAlchemy ORM. +Synopsis +======== + SQLAlchemy object-relational configuration involves the usage of Table, mapper(), and class objects to define the three areas of configuration. -declarative moves these three types of configuration underneath the individual +``declarative`` moves these three types of configuration underneath the individual mapped class. Regular SQLAlchemy schema and ORM constructs are used in most cases:: @@ -12,16 +15,30 @@ cases:: class SomeClass(Base): __tablename__ = 'some_table' - id = Column('id', Integer, primary_key=True) - name = Column('name', String(50)) + id = Column(Integer, primary_key=True) + name = Column(String(50)) Above, the ``declarative_base`` callable produces a new base class from which all mapped classes inherit from. When the class definition is completed, a new ``Table`` and ``mapper()`` have been generated, accessible via the ``__table__`` and ``__mapper__`` attributes on the ``SomeClass`` class. -You may omit the names from the Column definitions. Declarative will fill -them in for you:: +Defining Attributes +=================== + +:class:`~sqlalchemy.schema.Column` objects may be explicitly named, +including using a different name than the attribute in which they are associated. +The column will be assigned to the :class:`~sqlalchemy.schema.Table` using the +given name, and mapped to the class using the attribute name:: + + class SomeClass(Base): + __tablename__ = 'some_table' + id = Column("some_table_id", Integer, primary_key=True) + name = Column("name", String(50)) + +Otherwise, you may omit the names from the Column definitions. +Declarative will set the ``name`` attribute on the column when the class +is initialized:: class SomeClass(Base): __tablename__ = 'some_table' @@ -29,14 +46,19 @@ them in for you:: name = Column(String(50)) Attributes may be added to the class after its construction, and they will be -added to the underlying ``Table`` and ``mapper()`` definitions as +added to the underlying :class:`~sqlalchemy.schema.Table` and :func:`~sqlalchemy.orm.mapper()` definitions as appropriate:: SomeClass.data = Column('data', Unicode) SomeClass.related = relation(RelatedInfo) -Classes which are mapped explicitly using ``mapper()`` can interact freely -with declarative classes. +Classes which are mapped explicitly using :func:`~sqlalchemy.orm.mapper()` can interact freely +with declarative classes. It is recommended, though not required, that all tables +share the same underlying :class:`~sqlalchemy.schema.MetaData` object, so that +string-configured :class:`~sqlalchemy.schema.ForeignKey` references can be resolved without issue. + +Association of Metadata and Engine +================================== The ``declarative_base`` base class contains a ``MetaData`` object where newly defined ``Table`` objects are collected. This is accessed via the @@ -64,6 +86,9 @@ traditional collection of ``Table`` objects:: mymetadata = MetaData() Base = declarative_base(metadata=mymetadata) +Configuring Relations +===================== + Relations to other classes are done in the usual way, with the added feature that the class specified to ``relation()`` may be a string name. The "class registry" associated with ``Base`` is used at mapper compilation time to @@ -114,9 +139,12 @@ class after the fact:: User.addresses = relation(Address, primaryjoin=Address.user_id == User.id) -Synonyms are one area where ``declarative`` needs to slightly change the usual -SQLAlchemy configurational syntax. To define a getter/setter which proxies to -an underlying attribute, use ``synonym`` with the ``descriptor`` argument:: +Defining Synonyms +================= + +Synonyms are introduced in :ref:`synonyms`. To define a getter/setter which +proxies to an underlying attribute, use ``synonym`` with the +``descriptor`` argument:: class MyClass(Base): __tablename__ = 'sometable' @@ -125,7 +153,7 @@ an underlying attribute, use ``synonym`` with the ``descriptor`` argument:: def _get_attr(self): return self._some_attr - def _set_attr(self, attr) + def _set_attr(self, attr): self._some_attr = attr attr = synonym('_attr', descriptor=property(_get_attr, _set_attr)) @@ -136,7 +164,8 @@ class-level expression construct:: x.attr = "some value" session.query(MyClass).filter(MyClass.attr == 'some other value').all() -The `synonym_for` decorator can accomplish the same task:: +For simple getters, the :func:`synonym_for` decorator can be used in conjunction +with ``@property``:: class MyClass(Base): __tablename__ = 'sometable' @@ -148,7 +177,8 @@ The `synonym_for` decorator can accomplish the same task:: def attr(self): return self._some_attr -Similarly, `comparable_using` is a front end for the `comparable_property` ORM function:: +Similarly, :func:`comparable_using` is a front end for the :func:`~sqlalchemy.orm.comparable_property` +ORM function:: class MyClass(Base): __tablename__ = 'sometable' @@ -160,6 +190,9 @@ Similarly, `comparable_using` is a front end for the `comparable_property` ORM f def uc_name(self): return self.name.upper() +Table Configuration +=================== + As an alternative to ``__tablename__``, a direct ``Table`` construct may be used. The ``Column`` objects, which in this case require their names, will be added to the mapping just like a regular mapping to a table:: @@ -173,17 +206,20 @@ added to the mapping just like a regular mapping to a table:: Other table-based attributes include ``__table_args__``, which is either a dictionary as in:: - class MyClass(Base) + class MyClass(Base): __tablename__ = 'sometable' __table_args__ = {'mysql_engine':'InnoDB'} or a dictionary-containing tuple in the form ``(arg1, arg2, ..., {kwarg1:value, ...})``, as in:: - class MyClass(Base) + class MyClass(Base): __tablename__ = 'sometable' __table_args__ = (ForeignKeyConstraint(['id'], ['remote_table.id']), {'autoload':True}) +Mapper Configuration +==================== + Mapper arguments are specified using the ``__mapper_args__`` class variable. Note that the column objects declared on the class are immediately usable, as in this joined-table inheritance example:: @@ -470,44 +506,44 @@ def declarative_base(bind=None, metadata=None, mapper=None, cls=object, """Construct a base class for declarative class definitions. The new base class will be given a metaclass that invokes - `instrument_declarative()` upon each subclass definition, and routes + :func:`instrument_declarative()` upon each subclass definition, and routes later Column- and Mapper-related attribute assignments made on the class - into Table and Mapper assignments. See the `declarative` module - documentation for examples. + into Table and Mapper assignments. - bind - An optional `Connectable`, will be assigned to the `metadata.bind`. + :param bind: An optional :class:`~sqlalchemy.engine.base.Connectable`, will be assigned + the ``bind`` attribute on the :class:`~sqlalchemy.schema.MetaData` instance. The `engine` keyword argument is a deprecated synonym for `bind`. - metadata - An optional `MetaData` instance. All Tables implicitly declared by + :param metadata: + An optional :class:`~sqlalchemy.schema.MetaData` instance. All :class:`~sqlalchemy.schema.Table` + objects implicitly declared by subclasses of the base will share this MetaData. A MetaData instance will be create if none is provided. The MetaData instance will be available via the `metadata` attribute of the generated declarative base class. - mapper - An optional callable, defaults to `sqlalchemy.orm.mapper`. Will be + :param mapper: + An optional callable, defaults to :func:`~sqlalchemy.orm.mapper`. Will be used to map subclasses to their Tables. - cls - Defaults to `object`. A type to use as the base for the generated + :param cls: + Defaults to :class:`object`. A type to use as the base for the generated declarative base class. May be a type or tuple of types. - name - Defaults to 'Base', Python's internal display name for the generated + :param name: + Defaults to ``Base``. The display name for the generated class. Customizing this is not required, but can improve clarity in tracebacks and debugging. - constructor + :param constructor: Defaults to declarative._declarative_constructor, an __init__ implementation that assigns \**kwargs for declared fields and relations - to an instance. If `None` is supplied, no __init__ will be installed + to an instance. If ``None`` is supplied, no __init__ will be installed and construction will fall back to cls.__init__ with normal Python semantics. - metaclass - Defaults to `DeclarativeMeta`. A metaclass or __metaclass__ + :param metaclass: + Defaults to :class:`DeclarativeMeta`. A metaclass or __metaclass__ compatible callable to use as the meta type of the generated declarative base class. diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index aeb7d61af1..c96d8adf4b 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -749,51 +749,51 @@ class Column(SchemaItem, expression.ColumnClause): class ForeignKey(SchemaItem): """Defines a column-level FOREIGN KEY constraint between two columns. - ``ForeignKey`` is specified as an argument to a ``Column`` object. + ``ForeignKey`` is specified as an argument to a :class:`Column` object, e.g.:: + + t = Table("remote_table", metadata, + Column("remote_id", ForeignKey("main_table.id")) + ) - For a composite (multiple column) FOREIGN KEY, use a ForeignKeyConstraint - within the Table definition. + For a composite (multiple column) FOREIGN KEY, use a :class:`ForeignKeyConstraint` + object specified at the level of the :class:`Table`. + + Further examples of foreign key configuration are in :ref:`metadata_foreignkeys`. """ def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None): - """Construct a column-level FOREIGN KEY. + """ + Construct a column-level FOREIGN KEY. - column - A single target column for the key relationship. A ``Column`` + :param column: A single target column for the key relationship. A :class:`Column` object or a column name as a string: ``tablename.columnname`` or ``schema.tablename.columnname``. - constraint - Optional. A parent ``ForeignKeyConstraint`` object. If not - supplied, a ``ForeignKeyConstraint`` will be automatically created + :param constraint: Optional. A parent :class:`ForeignKeyConstraint` object. If not + supplied, a :class:`ForeignKeyConstraint` will be automatically created and added to the parent table. - name - Optional string. An in-database name for the key if `constraint` is + :param name: Optional string. An in-database name for the key if `constraint` is not provided. - onupdate - Optional string. If set, emit ON UPDATE when issuing DDL + :param onupdate: Optional string. If set, emit ON UPDATE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. - ondelete - Optional string. If set, emit ON DELETE when issuing DDL + :param ondelete: Optional string. If set, emit ON DELETE when issuing DDL for this constraint. Typical values include CASCADE, DELETE and RESTRICT. - deferrable - Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when + :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when issuing DDL for this constraint. - initially - Optional string. If set, emit INITIALLY when issuing DDL + :param initially: Optional string. If set, emit INITIALLY when issuing DDL for this constraint. - use_alter - If True, do not emit this key as part of the CREATE TABLE + :param use_alter: If True, do not emit this key as part of the CREATE TABLE definition. Instead, use ALTER TABLE after table creation to add the key. Useful for circular dependencies. + """ self._colspec = column @@ -1169,8 +1169,11 @@ class ForeignKeyConstraint(Constraint): Defines a single column or composite FOREIGN KEY ... REFERENCES constraint. For a no-frills, single column foreign key, adding a - ``ForeignKey`` to the definition of a ``Column`` is a shorthand equivalent - for an unnamed, single column ``ForeignKeyConstraint``. + :class:`ForeignKey` to the definition of a :class:`Column` is a shorthand equivalent + for an unnamed, single column :class:`ForeignKeyConstraint`. + + Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. + """ def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None):