I've always read that if you needed to centralize your logic, that you 
should use modules instead of trying to do it in a model or trying to wire 
up one controller to another. I used global settings as an example, as you 
might need access to these settings in every controller, and duplicating the 
code in every controller goes against the Python and we2py's DRY 
(don't repeat yourself) principal. So this is why modules were created.

Granted, the GlobalSettings object I demonstrated is a very basic object 
that doesn't require you to instantiate it because it's all static. However, 
if you want to use more sophisticated objects, then the static class method 
may not work well. So there's another way to do this that I've been playing 
with.

I am replacing a legacy application that is sort of like an ERP. The 
application keeps track of when employees clock in and clock out. Then, at 
the end of the week they print out their time cards. So, I wrote a TimeClock 
class in the same 'core.py' file described above. The big difference here is 
that the TimeClock object will have several functions, and I don't want to 
have to pass db, cache, and everything else for every function call, so I 
wrote it like this:

class TimeClock:
    def __init__(self, environment, db):
        self.env = Storage(environment)
        self.request = self.env.request
        self.response = self.env.response
        self.cache = self.env.cache
        self.db = db

    def is_employee_clocked_in(self, employee):
        db = self.db
        timeclock_entry = db((db.timeclock.employee==employee) & 
(db.timeclock.endtime==None)).select().first()
        if timeclock_entry is None:
            return False
        else:
            return True

Now, in my 'z_import_modules.py', I would add this (assuming I already did a 
local_import on core.py):

timeclock = core.TimeClock(globals(), db)

Then in any controller, if I want to check if an employee is clocked in:

employee = auth.user
if timeclock.is_employee_clocked_in(employee):
    print '%s is clocked in' % (employee.first_name)
else:
    print '%s is not clocked in' % (employee.first_name)

So with modules, you can make static classes for simple objects, like global 
settings that just load and save settings, or you can make complex objects 
that you instantiate in either the 'z_import_modules.py' file, or if you 
don't plan on using the module in every controller, then you could just 
remove the line we added in 'z_import_modules.py' to instantiate the 
'timeclock' object, and use that line in whatever controller action we want.

Hope this helps. So far this method seems to work really well. Oh, and to 
help you avoid some frustration in developing your modules, when you call 
local_import, you may also want to add reload=True to it. Without this, you 
would have to restart the web2py server every time you made a change to the 
module. Once you put your app into production, you would want to remove 
reload=True, as you don't want web2py to reload the module for every page 
load on a production server. So for testing, use this line:

core = local_import('core', reload=True)

And when you go into production, just remove 'reload=True'.

Reply via email to