Table Configuration

See also

This section describes specifics about how the Declarative systemdefines Table objects that are to be mapped with theSQLAlchemy ORM. For general information on Table objectssee Describing Databases with MetaData.

Table arguments other than the name, metadata, and mapped Columnarguments are specified using the table_args class attribute.This attribute accommodates both positional as well as keywordarguments that are normally sent to theTable constructor.The attribute can be specified in one of two forms. One is as adictionary:

  1. class MyClass(Base):
  2. __tablename__ = 'sometable'
  3. __table_args__ = {'mysql_engine':'InnoDB'}

The other, a tuple, where each argument is positional(usually constraints):

  1. class MyClass(Base):
  2. __tablename__ = 'sometable'
  3. __table_args__ = (
  4. ForeignKeyConstraint(['id'], ['remote_table.id']),
  5. UniqueConstraint('foo'),
  6. )

Keyword arguments can be specified with the above form byspecifying the last argument as a dictionary:

  1. class MyClass(Base):
  2. __tablename__ = 'sometable'
  3. __table_args__ = (
  4. ForeignKeyConstraint(['id'], ['remote_table.id']),
  5. UniqueConstraint('foo'),
  6. {'autoload':True}
  7. )

Using a Hybrid Approach with table

As an alternative to tablename, a directTable construct may be used. TheColumn objects, which in this case requiretheir names, will be added to the mapping just like a regular mappingto a table:

  1. class MyClass(Base):
  2. __table__ = Table('my_table', Base.metadata,
  3. Column('id', Integer, primary_key=True),
  4. Column('name', String(50))
  5. )

table provides a more focused point of control for establishingtable metadata, while still getting most of the benefits of using declarative.An application that uses reflection might want to load table metadata elsewhereand pass it to declarative classes:

  1. from sqlalchemy.ext.declarative import declarative_base
  2.  
  3. Base = declarative_base()
  4. Base.metadata.reflect(some_engine)
  5.  
  6. class User(Base):
  7. __table__ = metadata.tables['user']
  8.  
  9. class Address(Base):
  10. __table__ = metadata.tables['address']

Some configuration schemes may find it more appropriate to use table,such as those which already take advantage of the data-driven nature ofTable to customize and/or automate schema definition.

Note that when the table approach is used, the object is immediatelyusable as a plain Table within the class declaration body itself,as a Python class is only another syntactical block. Below this is illustratedby using the id column in the primaryjoin condition of arelationship():

  1. class MyClass(Base):
  2. __table__ = Table('my_table', Base.metadata,
  3. Column('id', Integer, primary_key=True),
  4. Column('name', String(50))
  5. )
  6.  
  7. widgets = relationship(Widget,
  8. 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:

  1. from sqlalchemy.ext.declarative import synonym_for
  2.  
  3. class MyClass(Base):
  4. __table__ = Table('my_table', Base.metadata,
  5. Column('id', Integer, primary_key=True),
  6. Column('name', String(50))
  7. )
  8.  
  9. _name = __table__.c.name
  10.  
  11. @synonym_for("_name")
  12. def name(self):
  13. return "Name: %s" % _name

Using Reflection with Declarative

It’s easy to set up a Table that uses autoload=Truein conjunction with a mapped class:

  1. class MyClass(Base):
  2. __table__ = Table('mytable', Base.metadata,
  3. autoload=True, autoload_with=some_engine)

However, one improvement that can be made here is to notrequire the Engine to be available when classes arebeing first declared. To achieve this, use theDeferredReflection mixin, which sets up mappingsonly after a special prepare(engine) step is called:

  1. from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
  2.  
  3. Base = declarative_base(cls=DeferredReflection)
  4.  
  5. class Foo(Base):
  6. __tablename__ = 'foo'
  7. bars = relationship("Bar")
  8.  
  9. class Bar(Base):
  10. __tablename__ = 'bar'
  11.  
  12. # illustrate overriding of "bar.foo_id" to have
  13. # a foreign key constraint otherwise not
  14. # reflected, such as when using MySQL
  15. foo_id = Column(Integer, ForeignKey('foo.id'))
  16.  
  17. Base.prepare(e)