Hi Alex,

Thanks for that.  I confirmed it works, kind of.

It seems the key was to put all the models into one package, do the
imports in the __init__.py, and import the package (my approach was
import the files in the package from a model.py file outside the
package).  Your approach works if you run the script, but it doesn't
quite work inside a turbogears environment.

Putting it into a turbogears project, there seems to be a problem
regarding where you put the setup_all. Here's the problem:
The way it "should work" is in your turbogears root controller, you
import the model package and use it:

controllers/root.py:
-------
...
from models_package import *
setup_all()

class Root(controllers.RootController):
  ....
-------

The problem, however, seems to be that when you launch the tg project
using $python start-tgproject.py, the metadata engine object created
by turbogears is not bound at the time when the root controller is
loaded, and this somehow causes the KeyError in the previous post (ie
the above root.py causes the previously-described KeyError with the
same symptoms).  At this point, the problem seems to be Turbogears
related, but I'd appreciate some Elixir-people help (see below) before
turning to the Turbogears board.

Anyways, there are two solutions I've found, but both seem hack-ish:
1) Bind the metadata object in the root controller:

controllers/root.py:
-------
...
from turbogears.database import metadata  #Wrapper for Elixir's
metadata object
metadata.bind = "mysql://multimodel:[EMAIL PROTECTED]:3306/
multifilemodel"

from models_package import *
setup_all()

class Root(controllers.RootController):
  ....
-------
but this is very hackish because we're overriding Turbogear's metadata
engine, which in general is a bad idea.


2) Import the models inside whichever root controller method needs
them:

controllers/root.py:
-------
...

class Root(controllers.RootController):
  ....

   @expose()
   def controller1(self):
      from models_package import *
      setup_all()
      ....

   @expose()
   def controller2(self):
      from models_package import *
      setup_all()
      ....
   ....
-------

But this also seems really hackish and just obnoxious to use.

So, any suggestions on:
A) Elixir: Why do we get the previously-described KeyError when there
is no bound metadata engine but don't get it when there IS a bound
metadata engine?
or
B) TurboGears: Whats the proper way of using the models in a
TurboGears project, given that turbogears does not seem to bind its
metadata object until after the root controller file is loaded?

-Dan

On Apr 25, 9:54 pm, alex23 <[EMAIL PROTECTED]> wrote:
> Hey Dan,
>
> I've had no problems splitting TG models across multiple files in the
> past. I generally set 'model' up as a package, so for your code above
> I'd structure it like so:
>
>     mmtest/
>         create_tables.py
>         model/
>             __init__.py
>             dog.py
>             man.py
>
> dog.py:
> -------
>     from elixir import Entity, Field, Unicode, ManyToOne
>
>     class Dog(Entity):
>         name = Field(Unicode(10))
>         owner = ManyToOne('Man')
>         def __repr__(self):
>             return '<Dog \'%s\'>' % (self.name)
>
> man.py:
> -------
>     from elixir import Entity, Field, Unicode, OneToMany
>
>     class Man(Entity):
>         name = Field(Unicode(10))
>         pets = OneToMany('Dog')
>         def __repr__(self):
>             return '<Man \'%s\'>' % (self.name)
>
> __init.py__:
> ------------
>     from elixir import setup_all
>
>     from dog import Dog
>     from man import Man
>
>     print "Man: %s" % Man.__metaclass__._entities
>     print "Dog: %s" % Dog.__metaclass__._entities
>
> create_tables.py:
> -----------------
>     from elixir import metadata, setup_all
>     from model import *
>
>     metadata.bind = "sqlite:///multifilemodel.db"
>
>     setup_all(True)
>
> Running create_tables.py gives me:
>
>     Man: {20702984: {'Man': <class 'model.man.Man'>,
>                      'Dog': <class 'model.dog.Dog'>,
>                      'Entity': <class 'elixir.entity.Entity'>}}
>     Dog: {20702984: {'Man': <class 'model.man.Man'>,
>                      'Dog': <class 'model.dog.Dog'>,
>                      'Entity': <class 'elixir.entity.Entity'>}}
>
> And more pertinently:
>
>     >sqlite3 multifilemodel.db
>     SQLite version 3.5.7
>     Enter ".help" for instructions
>     sqlite> .schema
>     CREATE TABLE model_dog_dog (
>             id INTEGER NOT NULL,
>             name VARCHAR(10),
>             owner_id INTEGER,
>             PRIMARY KEY (id),
>              CONSTRAINT model_dog_dog_owner_id_fk FOREIGN
> KEY(owner_id) REFERENCES model_man_man (id)
>     );
>     CREATE TABLE model_man_man (
>             id INTEGER NOT NULL,
>             name VARCHAR(10),
>             PRIMARY KEY (id)
>     );
>     CREATE INDEX ix_model_dog_dog_owner_id ON model_dog_dog
> (owner_id);
>
> This is all tested & working under Elixir 0.5.1.
>
> Hope this helps.
>
> - alex23
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"SQLElixir" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlelixir?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to