On Mon, Mar 3, 2014 at 10:38 AM, AM <[email protected]> wrote: > On 02/28/2014 11:58 PM, Chung WONG wrote: >> >> I have a *models.py* that contains 10 classes. And I am trying to move all >> classes out of that file and put each class into its own file under a models >> package. >> >> I am using the alternative(at bottom of page) method mentioned here >> <https://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/database/sqlalchemy.html#importing-all-sqlalchemy-models>, >> but I don't know how it works for initialise db script as it is using >> *config.scan()* >> >> However, when i ran *bin/initialize_bug_db development.in *to initialise >> the database, it threw such as : >> >> sqlalchemy.exc.InvalidRequestError: When initializing mapper >> Mapper|User|users, expression 'TopicUser' failed to locate a name ("name >> 'TopicUser' is not defined"). If this is a class name, consider adding this >> relationship() to the <class 'bug.models.user.User'> class after both >> dependent classes have been defined. >> >> which was caused by something like *topics = relationship('TopicUser', >> backref="user", lazy='dynamic')* >> >> and >> >> sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column >> 'notifications.topic_id' could not find table 'topics' with which to >> generate a foreign key to target column 'id' >> which was caused by something like *topic_id=Column(Integer, >> ForeignKey('topics.id'))*
It sounds like config.scan() is importing the modules in the wrong order. There's not much you can do about that. If your DeclarativeBase is in one module, the child model is in a second module, and the module with the relationship is in a third module, you have to import them in that order, and config.scan() can't guess that. I think you can define the models out of order by using a string in the relationship, but I've only done that within a module so I'm not sure it works across modules. AM's includeme() would be one way to address this, but the primary issue is what's *in* the includeme() and what's above it. You could have the includeme() body import the modules in the right order and configure everything. You would probably not want any unnecessary global-level imports above it, which might throw things off. I don't use includeme() in models but I do this instead: def init_models(engine): DBSession.bind = engine Base.metadata.bind = engine This is nice because it's one-stop initialization for both the application and any standalone scripts. It would also be the place to do any reflection or preloading memory indexes. You *can* do circular imports this way: # .__init__.py import sqlalchemy.orm as orm DBSession = orm.scoped_session(orm.sessionmaker(extension=...)) import submodule_a # submodule_a.py from . import DBSession The trick is that the "import submodule_a" must *below* anything that submodule_a imports from the parent module, because when submodule_a is initializing only the top part of the parent's module has executed. I didn't recommend it in the Cookbook article because I considered it failure-prone, but several people have successfully used it since then. I still prefer to avoid circular imports whenever possible. -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/pylons-discuss. For more options, visit https://groups.google.com/groups/opt_out.
