]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
more declarative doc updates
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 28 Apr 2008 00:04:05 +0000 (00:04 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 28 Apr 2008 00:04:05 +0000 (00:04 +0000)
doc/build/content/plugins.txt
lib/sqlalchemy/ext/declarative.py

index 0de25e2b79decf9751acb11ec8a8497c30d0ec3b..c144826d7bc46525429970367045b4c139e875f9 100644 (file)
@@ -19,8 +19,7 @@ in most cases:
     {python}
     from sqlalchemy.ext.declarative import declarative_base
     
-    engine = create_engine('sqlite://')
-    Base = declarative_base(engine)
+    Base = declarative_base()
     
     class SomeClass(Base):
         __tablename__ = 'some_table'
@@ -38,13 +37,25 @@ appropriate:
     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 as well as a dictionary of all classes created against the base. So to access the above metadata and create tables we can say:
+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:
 
     {python}
-    Base.metadata.create_all()
-    
-The `declarative_base` can also receive a pre-created `MetaData` object:
+    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 `engine` 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:
+
+    {python}
+    Base = declarative_base(engine=create_engine('sqlite://'))
+
+Or, as `MetaData` allows, at any time using the `bind` attribute:
+
+    {python}
+    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:
 
     {python}
     mymetadata = MetaData()
@@ -81,6 +92,16 @@ using them:
         user_id = Column('user_id', Integer, ForeignKey('users.id'))
         user = relation(User, primaryjoin=user_id==User.id)
 
+When an explicit join condition or other configuration which depends 
+on multiple classes cannot be defined immediately due to some classes
+not yet being available, these can be defined after all classes have
+been created.  Attributes which are added to the class after
+its creation are associated with the Table/mapping in the same
+way as if they had been defined inline:
+
+    {python}
+    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 `instruments` argument:
 
@@ -129,7 +150,8 @@ Similarly, `comparable_using` is a front end for the `comparable_property` ORM f
         def uc_name(self):
             return self.name.upper()
 
-As an alternative to `__tablename__`, a direct `Table` construct may be used:
+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:
+
 
     {python}
     class MyClass(Base):
index f1ab1311731551e607dc43127399fc2ce492309f..5bdd9652e516343a0e3480e5b50214fbeb0875f6 100644 (file)
@@ -22,7 +22,7 @@ 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.
+them in for you::
 
     class SomeClass(Base):
         __tablename__ = 'some_table'
@@ -37,24 +37,30 @@ appropriate::
     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 as well as a dictionary of all classes created against
-the base.  So to access the above metadata and create tables we can say::
+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::
 
     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 `engine` keyword argument, where it will 
-be associated with the underlying `MetaData` object and allow SQL 
+The ``Engine`` created above may also be directly associated with the 
+declarative base class using the ``engine`` 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::
 
-    {python}
     Base = declarative_base(engine=create_engine('sqlite://'))
 
+Or, as ``MetaData`` allows, at any time using the ``bind`` attribute::
+
+    Base.metadata.bind = create_engine('sqlite://')
+
 The ``declarative_base`` can also receive a pre-created ``MetaData``
-object::
+object, which allows a declarative setup to be associated with an already existing traditional collection of ``Table`` objects::
 
     mymetadata = MetaData()
     Base = declarative_base(metadata=mymetadata)
@@ -91,6 +97,15 @@ using them::
         user_id = Column(Integer, ForeignKey('users.id'))
         user = relation(User, primaryjoin=user_id==User.id)
 
+When an explicit join condition or other configuration which depends 
+on multiple classes cannot be defined immediately due to some classes
+not yet being available, these can be defined after all classes have
+been created.  Attributes which are added to the class after
+its creation are associated with the Table/mapping in the same
+way as if they had been defined inline::
+
+    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``
@@ -115,12 +130,13 @@ class-level expression construct::
     session.query(MyClass).filter(MyClass.attr == 'some other value').all()
 
 As an alternative to ``__tablename__``, a direct ``Table`` construct may be
-used::
+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::
 
     class MyClass(Base):
         __table__ = Table('my_table', Base.metadata,
-            Column(Integer, primary_key=True),
-            Column(String(50))
+            Column('id', Integer, primary_key=True),
+            Column('name', String(50))
         )
 
 This is the preferred approach when using reflected tables, as below::