Re: [sqlalchemy] Using the declarative base across projects

2010-07-20 Thread thatsanicehatyouhave
Hi,

Just wanted to say thanks to those who helped me with this. Simon's solution 
was exactly what I was looking for (though I have to admit I don't exactly 
understand *how* it works!). But that's no longer an SQLAlchemy question...

Cheers,
Demitri

On Jul 8, 2010, at 5:49 AM, King Simon-NFHD78 wrote:

 In general, you don't need a database connection just to define your
 tables and mappers. The 'bind' parameter to DeclarativeBase is optional,
 and only necessary if you are using autoloading. So one solution to your
 problem would be not to use autoloading, and bind to a database at the
 Session level rather than the Mapper level. That would be the usual way
 to use the same set of classes against multiple databases.
 
 If you really need to use autoloading, you could move all your class
 definitions into a function that accepts a database engine as a
 parameter. For example:
 
 #
 # ModelClasses.py
 
 class Namespace(object):
   def __init__(self, **kwargs):
   self.__dict__.update(kwargs)
 
 
 def initdb(connection_string):
   engine = create_engine(connection_string)
   Base = declarative_base(bind=engine)
 
   class Table1(Base):
   __tablename__ = 'table1'
   __table_args__ = {'autoload': True}
 
 
   return Namespace(Base=Base,
Table1=Table1)
 
   # or, you could be lazy:
   # return Namespace(**locals())
 
 
 
 
 # MainScript1.py
 import ModelClasses
 
 db = ModelClasses.initdb(my_connection_string)
 
 # access db.Table1, db.Base etc.
 
 
 
 Hope that helps,
 
 Simon

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Using the declarative base across projects

2010-07-08 Thread Chris Withers

thatsanicehatyouh...@mac.com wrote:

This is a bit tricky to explain. Imagine I have one database, and I create a 
project (1) to work with that database (connections, table class definitions, 
etc.). That is standalone (to me). I have another completely separate database 
(2) on another host where I do the same thing. Using replication I then create 
a read-only copy of database 1 in database 2, and join some of the tables. 
Project 2 needs to generate the classes, but use SA's Base class that is 
dynamically generated. Since it's dynamic, I have to create it at run time... 
but now I can't pass that to the definition of project 1's classes. It's that 
communication that I'm struggling with.


Difficult to know what you're after so two guesses:

- if you have multiple python packages that need to share a declarative 
Base, either have one master package that defines the Base and import 
from that or, if you prefer completely normalised dependencies, move the 
Base definition out its own package (where stuff shared between your 
packages such as mixins, session setup functions, etc can live) and have 
both packages import from there.


- if you have different python packages on two different projects 
running on two different machines or in different processes, then just 
have each create their own Base. The Base is merely a collection of 
references to the SA mapped classes, much like the MetaData object, so 
it's fine to have different ones in different processes, even if they're 
both accessing the same tables in the same databases...


cheers,

Chris

--
Simplistix - Content Management, Batch Processing  Python Consulting
   - http://www.simplistix.co.uk

--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



RE: [sqlalchemy] Using the declarative base across projects

2010-07-08 Thread King Simon-NFHD78
 -Original Message-
 From: sqlalchemy@googlegroups.com 
 [mailto:sqlalch...@googlegroups.com] On Behalf Of 
 thatsanicehatyouh...@mac.com
 Sent: 07 July 2010 20:33
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] Using the declarative base across projects
 
 Hi Lance,
 
 Thanks for your comments.
 
 On Jul 7, 2010, at 12:28 PM, Lance Edgar wrote:
 
  Why not just do this in project2 ?
  
  
  import project.DatabaseConnection as db
  
  Base = declarative_base(bind=db.engine)
  
  # ... etc.
 
 The DatabaseConnection class contains the particulars of the 
 connection (i.e. host, username, password) which can be 
 different. I don't want to create dependencies between the 
 projects, I just want to reuse the class definitions. I want 
 to create the DatabaseConnection once and pass it into the 
 definition of the classes.
 
 Another approach I tried was to make ModelClasses an object 
 and define the classes in a method there (so I could just 
 pass the Base class to it), but the class definitions were in 
 the wrong namespace.
 
  The python way seems to be to create a config class, 
 but project2.ModelClasses won't know anything about it if 
 it's defined in the first project. As to the reason why there 
 are two separate projects, consider the case where one set of 
 tables is one logical group, and the second is a replicated 
 copy from another server. I can't merge all of these projects 
 since they really are independent units, but sometimes I 
 will link them (as above).
  
  I don't understand why project2 wouldn't know anything 
 about it if defined in (first) project.  All it needs to do 
 is import the connection info from the project (as in above 
 example).  If the database configuration really transcends 
 both project and project2 though, then yes it probably could 
 be wrapped in a config module of some sort in another 
 project; depending on the scope that may be a bit overkill.  
 If you can consider either project or project2 to be 
 slightly more default than the other then the db config could 
 stay there I'd think.
 
 This is a bit tricky to explain. Imagine I have one database, 
 and I create a project (1) to work with that database 
 (connections, table class definitions, etc.). That is 
 standalone (to me). I have another completely separate 
 database (2) on another host where I do the same thing. Using 
 replication I then create a read-only copy of database 1 in 
 database 2, and join some of the tables. Project 2 needs to 
 generate the classes, but use SA's Base class that is 
 dynamically generated. Since it's dynamic, I have to create 
 it at run time... but now I can't pass that to the definition 
 of project 1's classes. It's that communication that I'm 
 struggling with.
 
 Cheers,
 Demitri
 

In general, you don't need a database connection just to define your
tables and mappers. The 'bind' parameter to DeclarativeBase is optional,
and only necessary if you are using autoloading. So one solution to your
problem would be not to use autoloading, and bind to a database at the
Session level rather than the Mapper level. That would be the usual way
to use the same set of classes against multiple databases.

If you really need to use autoloading, you could move all your class
definitions into a function that accepts a database engine as a
parameter. For example:

#
# ModelClasses.py

class Namespace(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)


def initdb(connection_string):
engine = create_engine(connection_string)
Base = declarative_base(bind=engine)

class Table1(Base):
__tablename__ = 'table1'
__table_args__ = {'autoload': True}


return Namespace(Base=Base,
 Table1=Table1)

# or, you could be lazy:
# return Namespace(**locals())




# MainScript1.py
import ModelClasses

db = ModelClasses.initdb(my_connection_string)

# access db.Table1, db.Base etc.



Hope that helps,

Simon

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Using the declarative base across projects

2010-07-07 Thread Lance Edgar
On Wed, 2010-07-07 at 11:13 -0400, thatsanicehatyouh...@mac.com wrote:

 Hi,
 
 I have a question that I can't find a satisfactory answer to. Apologies in 
 advance if it's more of a Python question, but it's possible that there is a 
 SA solution.
 
 I have a project that defines a database connection and classes based on 
 database tables. A script that uses these classes would start with:
 
 import project.DatabaseConnection as db # create_engine() and metadata 
 defined here
 import project.ModelClasses
 
 In ModelClasses, I define all of the table classes using:
 
 Base = declarative_base(bind=db.engine)
 
 class Table1(Base):
   __tablename__ = 'table1'
   __table_args__ = {'autoload' : True} # requires metadata to work
 
 
 This is fine. I have a second project that also defines a different set of 
 tables that I want to use, so the main script would then:
 
 import project2.ModelClasses # a different set of tables
 
 If it's not clear how the db parameter (the database connection) was 
 defined in ModelClasses, well, that's my problem. I can't pass a parameter to 
 an import statement of course. The DatabaseConnection class defines the 
 engine and metadata, and now I need to use these objects to generate my base 
 class. How can I pass this object around? Should I be using a different model?


Why not just do this in project2 ?


import project.DatabaseConnection as db

Base = declarative_base(bind=db.engine)

# ... etc.



 The python way seems to be to create a config class, but 
 project2.ModelClasses won't know anything about it if it's defined in the 
 first project. As to the reason why there are two separate projects, consider 
 the case where one set of tables is one logical group, and the second is a 
 replicated copy from another server. I can't merge all of these projects 
 since they really are independent units, but sometimes I will link them (as 
 above).



I don't understand why project2 wouldn't know anything about it if
defined in (first) project.  All it needs to do is import the connection
info from the project (as in above example).  If the database
configuration really transcends both project and project2 though, then
yes it probably could be wrapped in a config module of some sort in
another project; depending on the scope that may be a bit overkill.  If
you can consider either project or project2 to be slightly more
default than the other then the db config could stay there I'd think.

Lance

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] Using the declarative base across projects

2010-07-07 Thread thatsanicehatyouhave
Hi Lance,

Thanks for your comments.

On Jul 7, 2010, at 12:28 PM, Lance Edgar wrote:

 Why not just do this in project2 ?
 
 
 import project.DatabaseConnection as db
 
 Base = declarative_base(bind=db.engine)
 
 # ... etc.

The DatabaseConnection class contains the particulars of the connection (i.e. 
host, username, password) which can be different. I don't want to create 
dependencies between the projects, I just want to reuse the class definitions. 
I want to create the DatabaseConnection once and pass it into the definition 
of the classes.

Another approach I tried was to make ModelClasses an object and define the 
classes in a method there (so I could just pass the Base class to it), but the 
class definitions were in the wrong namespace.

 The python way seems to be to create a config class, but 
 project2.ModelClasses won't know anything about it if it's defined in the 
 first project. As to the reason why there are two separate projects, 
 consider the case where one set of tables is one logical group, and the 
 second is a replicated copy from another server. I can't merge all of these 
 projects since they really are independent units, but sometimes I will 
 link them (as above).
 
 I don't understand why project2 wouldn't know anything about it if defined 
 in (first) project.  All it needs to do is import the connection info from 
 the project (as in above example).  If the database configuration really 
 transcends both project and project2 though, then yes it probably could be 
 wrapped in a config module of some sort in another project; depending on the 
 scope that may be a bit overkill.  If you can consider either project or 
 project2 to be slightly more default than the other then the db config 
 could stay there I'd think.

This is a bit tricky to explain. Imagine I have one database, and I create a 
project (1) to work with that database (connections, table class definitions, 
etc.). That is standalone (to me). I have another completely separate database 
(2) on another host where I do the same thing. Using replication I then create 
a read-only copy of database 1 in database 2, and join some of the tables. 
Project 2 needs to generate the classes, but use SA's Base class that is 
dynamically generated. Since it's dynamic, I have to create it at run time... 
but now I can't pass that to the definition of project 1's classes. It's that 
communication that I'm struggling with.

Cheers,
Demitri

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.