]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Declarative supports a __table_args__ class variable, which
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 9 Jul 2008 20:38:35 +0000 (20:38 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 9 Jul 2008 20:38:35 +0000 (20:38 +0000)
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]

CHANGES
doc/build/content/plugins.txt
lib/sqlalchemy/ext/declarative.py
test/ext/declarative.py

diff --git a/CHANGES b/CHANGES
index 8d83e7916849a640be4d987b163650e9ebffccf5..8142601203f895fb0661e21f1b7203dd189753b7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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
 ========
index 6e941cb9d43d622d68a25f752bd112f0d695f2e6..5f795d49743115b01e563cae40743534ed284e0a 100644 (file)
@@ -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:
index e69c5f23223e8f35fa7917a39f6422729085dd43..cd7efbc177268f693c5604a28ce57d0f2f602148 100644 (file)
@@ -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__
 
index ebe608c321b50fc9d56b1dbb41408567b565816f..21947b1e654a39b7158fe0b895e2b768e97d38db 100644 (file)
@@ -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'