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 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-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-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.



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.



[sqlalchemy] Using the declarative base across projects

2010-07-07 Thread thatsanicehatyouhave
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?

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).

Any advice would be greatly appreciated!

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.