Another very useful video - thanks for putting these out! Clever use of 
decorators for template support.

While we're on the topic of using web2py features outside of web2py:

I have a package with library code, command line scripts, etc. -- let's call 
it "mypackage"

Let's say I also have a web2py app "myapp".  (the creative juices are really 
flowing this morning!)

I want to be able to use the same DAL definition from:
 - myapp web2py controllers
 - mypackage command line scripts
 - mypackage library functions that may be called by either web2py or the 
command line scripts

Are there any generally accepted "best" methods for organizing something 
like this? I can think of the following general approaches:

1. - Define my DAL in myapp's models/db.py, as usual
    - Within mypackage code, do "from web2py.applications.myapp.models.db 
import db".

This has the following issues:
  (a.) I need to lug around my website code on machines where I want 
mypackage, even if I don't want to run the website
  (b.) If models/db.py is imported from outside web2py (e.g. a command line 
script), the contents only get evaluated once per execution. So I would only 
ever have a reference to one DB connection, which I think will cause 
problems if it is used from multiple threads. (Is this still correct?)
  (c.) Minor: I need to add "from gluon.dal import DAL, Field" to the top of 
db.py in models. Otherwise, imports from outside web2py will fail since 
db.py isn't being evaluated in web2py's context of preloaded gluon imports. 
I don't think this causes any problems, does it? It's just redundant when 
run within web2py?

2. A variant of #1: 

myapp/models/db.py:
  def get_db():    
    db = DAL(...)   # Put this in a function, so it can be evaluated 
multiple times at runtime
    db.define_table(...)
    return db

myapp/models/db_load.py:  # Gets loaded by web2py after db.py?
  db = get_db()  # We don't want this in db.py, or we'll have an extra 
connection hanging around in mypackage code

mypackage/my-script.py:
  from web2py.applications.myapp.models.db import get_db
  def threadedRoutine():
    db = get_db()
    do_stuff_within_thread(db)

I think this takes care of problem 1.b above.

3. Define my DAL in mypackage, and import from there in the web2py models. 
For example:

mypackage/db.py:
  db = DAL(...)
  db.define_table(...)

myapp/models/db.py:
  from mypackage.db import db  # warning - db only built once per server 
lifetime?

This has the following problems;
  - If I make changes to the DAL definition under mypackage/db.py, I think 
I'll need to restart the web2py server -- these changes won't be picked up 
automatically since they are in an outside module, right?
  - If the module is only evaluated once per execution, as with #1.b. you 
again have the problem of only one DAL instance, and this will cause 
problems when multiple connections/threads are involved. But this time the 
problem extends to web2py, not just mypackage! Am I correct in saying this, 
or does DAL have any magic that allow multiple threads to work via a single 
DAL reference?

But at least I don't need to carry my website code everywhere!

4.Like #3, define the DAL in mypackage and import into web2py models. But 
construct and return the database within a get_db() function, as with #2. 
Call get_db() from myapp/models/db.py to load a new DAL on each pageview, 
and from any mypackage thread that needs to use the db.

I think this is pretty good, except that you still need to restart web2py 
when making changes to the DAL. Maybe if models/db.py looked something like:

import mypackage.db  # contents are normally evaluated once per execution
reload(mypackage.db) # force mypackage.db to be re-read each time 
models/db.py is run
db = mypackage.db.get_db()

it would work, but I haven't tested it yet.


If anybody out there has successfully organized a setup like this or could 
offer any suggestions, I'd greatly appreciate it!

Thanks,
Kevin

Reply via email to