diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-07-09 20:38:35 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-07-09 20:38:35 +0000 |
commit | 5d375cd730fa0a89cb6684df47b2ae10cc217f57 (patch) | |
tree | ab10e8b156e543e9b365c45d41a889ea22d59aa9 | |
parent | ff9c5007a87c830fb763b43b451db3e4f002c31f (diff) | |
download | sqlalchemy-5d375cd730fa0a89cb6684df47b2ae10cc217f57.tar.gz |
- Declarative supports a __table_args__ class variable, which
is either a dictionary, or tuple of the form
(arg1, arg2, ..., {kwarg1:value, ...}) which contains positional
+ kw arguments to be passed to the Table constructor.
[ticket:1096]
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | doc/build/content/plugins.txt | 16 | ||||
-rw-r--r-- | lib/sqlalchemy/ext/declarative.py | 32 | ||||
-rw-r--r-- | test/ext/declarative.py | 18 |
4 files changed, 62 insertions, 11 deletions
@@ -83,6 +83,13 @@ CHANGES If you'd like them to return datetime objects anyway despite their accepting strings as input, make a TypeDecorator around String - SQLA doesn't encourage this pattern. + +- extensions + - Declarative supports a __table_args__ class variable, which + is either a dictionary, or tuple of the form + (arg1, arg2, ..., {kwarg1:value, ...}) which contains positional + + kw arguments to be passed to the Table constructor. + [ticket:1096] 0.5beta1 ======== diff --git a/doc/build/content/plugins.txt b/doc/build/content/plugins.txt index 6e941cb9d..5f795d497 100644 --- a/doc/build/content/plugins.txt +++ b/doc/build/content/plugins.txt @@ -171,11 +171,21 @@ As an alternative to `__tablename__`, a direct `Table` construct may be used. T Column('name', String(50)) ) -This is the preferred approach when using reflected tables, as below: +Other table-based attributes include `__table_args__`, which is +either a dictionary as in: {python} - class MyClass(Base): - __table__ = Table('my_table', Base.metadata, autoload=True) + class MyClass(Base) + __tablename__ = 'sometable' + __table_args__ = {'mysql_engine':'InnoDB'} + +or a dictionary-containing tuple in the form +`(arg1, arg2, ..., {kwarg1:value, ...})`, as in: + + {python} + 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: diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index e69c5f232..cd7efbc17 100644 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -146,10 +146,19 @@ added to the mapping just like a regular mapping to a table:: Column('name', String(50)) ) -This is the preferred approach when using reflected tables, as below:: +Other table-based attributes include ``__table_args__``, which is +either a dictionary as in:: - class MyClass(Base): - __table__ = Table('my_table', Base.metadata, autoload=True) + 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) + __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 @@ -237,11 +246,20 @@ def _as_declarative(cls, classname, dict_): if '__table__' not in cls.__dict__: if '__tablename__' in cls.__dict__: tablename = cls.__tablename__ + + table_args = cls.__dict__.get('__table_args__') + if isinstance(table_args, dict): + args, table_kw = (), table_args + elif isinstance(table_args, tuple): + args = table_args[0:-1] + table_kw = table_args[-1] + else: + args, table_kw = (), {} + autoload = cls.__dict__.get('__autoload__') if autoload: - table_kw = {'autoload': True} - else: - table_kw = {} + table_kw['autoload'] = True + cols = [] for key, c in our_stuff.iteritems(): if isinstance(c, ColumnProperty): @@ -253,7 +271,7 @@ def _as_declarative(cls, classname, dict_): _undefer_column_name(key, c) cols.append(c) cls.__table__ = table = Table(tablename, cls.metadata, - *cols, **table_kw) + *(tuple(cols) + tuple(args)), **table_kw) else: table = cls.__table__ diff --git a/test/ext/declarative.py b/test/ext/declarative.py index ebe608c32..21947b1e6 100644 --- a/test/ext/declarative.py +++ b/test/ext/declarative.py @@ -2,7 +2,7 @@ import testenv; testenv.configure_for_tests() from sqlalchemy.ext import declarative as decl from testlib import sa, testing -from testlib.sa import MetaData, Table, Column, Integer, String, ForeignKey +from testlib.sa import MetaData, Table, Column, Integer, String, ForeignKey, ForeignKeyConstraint from testlib.sa.orm import relation, create_session from testlib.testing import eq_ from testlib.compat import set @@ -255,7 +255,23 @@ class DeclarativeTest(testing.TestBase, testing.AssertsExecutionResults): sa.exc.ArgumentError, "Mapper Mapper|User|users could not assemble any primary key", define) + + def test_table_args(self): + class Foo(Base): + __tablename__ = 'foo' + __table_args__ = {'mysql_engine':'InnoDB'} + id = Column('id', Integer, primary_key=True) + + assert Foo.__table__.kwargs['mysql_engine'] == 'InnoDB' + class Bar(Base): + __tablename__ = 'bar' + __table_args__ = (ForeignKeyConstraint(['id'], ['foo.id']), {'mysql_engine':'InnoDB'}) + id = Column('id', Integer, primary_key=True) + + assert Bar.__table__.c.id.references(Foo.__table__.c.id) + assert Bar.__table__.kwargs['mysql_engine'] == 'InnoDB' + def test_expression(self): class User(Base, ComparableEntity): __tablename__ = 'users' |