>
> What I don't like about this is that it means the DB-setup code is run
>>> multiple times on a "normal" request. That is, if I have code to set up
>>> the DB in my model file, and I visit my db-accessing controller, it runs
>>> the code in the model file to set up the DB, then runs the code again when
>>> it runs the controller file. I imagine this is not a huge penalty but it
>>> is annoying.
>>>
>>
>> So, then don't do it that way. You have two options. First, if you have a
>> controller that doesn't need any of the model definitions from your
>> application's model files, then you should probably re-architect your
>> application so only the models that are needed get defined when they are
>> needed (either using the conditional models functionality or by defining
>> all models in modules that are imported where needed).
>>
>
> Not sure what you mean there about the models. What you describe is the
> opposite of my situation. My controller does need the models. That is
> exactly the problem, because I want to call that controller from another
> controller, but to do so I need the model files to be run.
>
You said you were running the db setup code twice. Since the second run
overwrites the first, by definition you must not need the first, so just
avoid running it the first time.
> The other option is simply to avoid re-running the DB setup code and
>> instead use the already defined db object, passing it to the module code
>> from the other app:
>>
>> app1/models/db.py:
>>
>> db = DAL(...)
>>
>> app2/modules/db_definer.py:
>>
>> def define_tables(db):
>> db.define_table('my_app2_table', ...)
>>
>> app1/controllers/default.py:
>>
>> from app2.modules.db_definer import define_tables
>>
>> def myfunc():
>> define_tables(db)
>> ...
>>
>> The above assumes both apps are using the same database, but if they are
>> not, then there is no "re-running the DB setup code" anyway, as you would
>> be dealing with two different databases, which would each need their own
>> setup code.
>>
>>
>
> What already-defined DB object?
>
You weren't quite clear about what you were doing. You showed the following
code:
from applications.otherapp.modules.db_definer
db = db_definer.define_db()
and complained that the code to create the "db" object was being run twice
(presumably once in this app's model files, and once in the db_definer
module from otherapp). My suggestion is that if both "db" objects are for
the same database, then just create the "db" object once (i.e., in this
app's model files) and pass it to any module code that needs to define
specific tables (i.e., don't create the "db" object in the module).
> If I use exec_environment, model files aren't run, so there is no db
> object.
>
My assumption is we are not using exec_environment here. I don't think that
will be a fruitful approach.
> Anyway, your response makes me think maybe I haven't explained my
> situation correctly. What I have this: controllerA.py and controllerB both
> needs the model in modelA.py controllerB wants to call a function in
> controllerA. What I want is a way, from within controller B, to say "run
> controllerA, making sure all the models it needs are available to it, and
> then give me controllerA as a module object (or something equivalent), so
> that I can call controllerA.some_function() and get the results". All
> without any additional network requests. (In fact, some_function is a
> service, so I will pass arguments to it.).
>
> If you need to share code across applications, I suggest you put that code
>> into modules and then import in whatever applications need the
>> functionality. Of course, you can also make internal HTTP requests from one
>> application to another (or use an RPC mechanism).
>>
>
> How would such code access the DB? By putting the define_tables-type code
> at the module top-level? Or by putting it in a function and having every
> db-accessing function call "db = get_DB()" at the beginning?
>
Those are not the only options. First, note that you can separate the
creation of the DAL object and the defining of its tables. You could have
one function in a module define the DAL object for a given database and
call that function from the model file of any given app. You can then have
different functions for defining various models, and those functions can be
called from anywhere -- a model, the top level of a controller, within a
controller function, or even another module.
> That seems similar to what I'm doing, except that the code is in a
> controller instead of a module. It seems the bottom line is that there is
> no way for a controller to internally specify a "dependency" on particular
> models.
>
If you create functions in modules to define the models, you can specify
the dependency by importing the module from the controller.
> The normal web2py mechanism will run the right model files on a regular
> HTTP request (based on the naming conventions), but if you want to call the
> controller file some other way, it will have to run the model-creation code
> itself, even if that code has already been run in another controller.
> There isn't a way to say "if such-and-such tables have already been
> created, give me the existing db object; otherwise, create them now". Is
> that right?
>
The simplest approach is to put shared functionality into modules. Of
course, if you don't know in what context a given bit of code will run, you
can easily check whether particular tables have been defined and then call
the table defining code if necessary.
Maybe it would help to show some actual code from two apps that you would
like to share.
Anthony
--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.