so you were missing the table logic creation. There are two methods: db.define_table('test1', Field('foo') ) db.define_table('test2', Field('bar', db.test1) )
or db.define_table('test2', Field('bar', 'reference test1') ) So. 1st method needs db.test1 defined in the environment. If you move test1 definition in another model, test2 'bar' column can't know what db.test1 is, so it fails ("python issue", it can't find the variable referenced as db.test1). It will always fail if db.test1 isn't defined (read, the model it's written into is not executed) when test2 definition is called. You're using the 2nd method (GOOD, it's the recommended one). If you move test1 definition in another model, as soon as test2 definition is reached, web2py will try to create the test2 table, and then fires the command to create the reference in the db between test1.id and test2.bar . This is done without knowing what db.table1 is, so it can be safely used in this kind of environments. But, if your table1 isn't in the db (I'm NOT talking about the python side, but the database side), then the command issued by web2py fails, and you get that traceback. So, 'reference something' allows you to have working references (even circular ones, that would be impossible with the 1st notation), as long as the table you are referencing exists yet in the DB, shortcutting the limits of the python interpreter. Clearer ? --