Reputation: 153
My controller file is getting pretty huge so I've decided to start splitting it up to smaller methods and take the methods to multiple module files. First thing, is this clever? Is this the pythonic/web2py way?
Anyway, I create my first module file my_module.py
in the Modules section (where there is __init__.py
already). I define a method my_method()
in the module. I import the module in my controller: import my_module
and call the method in the controller: my_module.my_method()
controller:
import my_module
...
def my_page():
...
my_module.my_method()
...
module:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from gluon import *
def my_method():
...
rows = db(db.my_table.my_field == x).select()
...
However, now it gives me error:
File "/home/my_user/web2py/applications/my_app/controllers/default.py", line 568, in my_page
my_module.my_method()
File "applications/my_app/modules/my_module.py", line 10, in my_method
rows = db(db.my_table.my_field == x).select()
NameError: global name 'db' is not defined
I'm doing pretty basic db stuff and the method worked fine when it was defined in the controller itself. But why does the module work differently to the controller? Are there any other differences or caveats? Is using modules even worth it?
Upvotes: 2
Views: 1137
Reputation: 25536
web2py executes model, controller, and view files in a prepared environment (which is created fresh on each HTTP request). Objects defined in model files (including the db
object) are added to this environment and therefore available globally within any controller or view. However, modules imported into controllers work the same as any other Python module -- they are not executed in the web2py environment, and therefore, objects in the web2py environment are not globally available within imported modules.
In this case, you have a couple options. First, you could simply pass the db
object to the function as an argument:
In the module:
def my_method(db):
In the controller:
my_module.my_method(db)
Alternatively, you could add the db
object to the current
object and import current
into the module (as documented here):
In a model:
from gluon import current
current.db = db
In your module:
from gluon import current
def my_method():
db = current.db # Keep this inside the function, not at the top level of the module.
Finally, note that you can also access any objects in the web2py environment via the current.globalenv
dictionary, so rather than explicitly adding db
to current
, you could simple access it via current.globalenv['db']
.
Upvotes: 2