I've been considering some issues related to this. Where do people
tend to locate their functions they are calling from controllers?

Obviously the simplest place is as a function defined in the same
controller python file as where it is called from. But some down sides
to this are:

* You end up with a handful of very large files in the controllers
folder
* Those functions can be potentially called as a URL via web2py

Maybe an example might clarify. Say you want to combine data from a
couple of tables from the DB. You might need to do this in a few
places in your controllers. You get back a list of some items, that
are going to be displayed as a table.

If the helper function is *purely* data driven, maybe you place it in
the models folder. The function is then put in the global namespace,
and can be called from any controller (I think, is that correct?)

More likely, the helper function might grab some data, and get it in
to a form that will be easy to display in a view. For example, if you
have a view layout with three columns, you might have all your
controllers return 3 bits of content for each column, and so need to
call 3 helper functions, one for each column's content that will be
displayed.

Now in this case, the modules folder can be useful for some cases, but
you need ot pass items that are normally in the global namespace, for
example the db. You also need to import the gluon modules.

So in summary, I can see a range of places to put these sort of
functions, but they all seem to have a down side:

* Models folder - Probably only appropriate if they are pure data
manipulation
* Modules folder - Great for functional code that is highly decoupled,
but you need to pass items like the db that are normally in the
controllers global namespace
* Down the bottom of an existing controller file - Easiest approach,
but your controller files quickly fill up with helper code. Doesn't
really hide complexity. Extra controller functions can be called if
someone enters the right URL
* In helper files in the controllers folder - Better than down the
bottom of an existing controller file, but I can't get these files to
be imported in other controllers, and these functions could still be
called via the right URL

What are people's solutions to making their controller code more
modular?

On Jun 5, 3:40 am, Thadeus Burgess <[email protected]> wrote:
> All functions defined in models are available to controllers and views
> as anything you put in the models becomes part of the global namespace
> that the controllers/views are executed in.
>
> This leads to potential problems of namespace collision.
>
> Make sure you do not overwrite the function elsewhere, as this could
> be causing issues.
>
> Why are you calling db.create_object? This isn't a class of the DAL,
> refer to Yarko's explanation, the DAL is not an ORM.
>
> You probably mean.
>
>   if form.accepts(request.vars, session):
>        foo = create_object(owner_id=auth.auth_id, # NOT
> db.create_object, just call your function like regular
> template_name=form.vars.template)
>
> --
> Thadeus
>
>
>
> On Fri, Jun 4, 2010 at 11:39 AM, Doug Warren <[email protected]> wrote:
> > On Fri, Jun 4, 2010 at 9:11 AM, Yarko Tymciurak
> > <[email protected]> wrote:
>
> >> On Jun 4, 10:58 am, Doug Warren <[email protected]> wrote:
> >>> I don't believe I want to local_import my db.py file as it's already
> >>> set up by the environment correct?
>
> >> Correct - you do not want / need to import your db.py.
>
> >> As long as it is in your modelsfolder(by default it is), it's
> >> already in your request context before your controller is called.
>
> > Yes but as I mentioned in my original E-Mail, I was unable to get a
> > function defined in the model file to be visible to the controller
> > hence the original question. :)
>
> > I thought about it a bit during my drive and think I will try (using
> > the below example) something like:
> > def create_object...
> > ...
>
> > co = create_object
>
> > controller.py
> >  co( template_id ...)
>
> >>> What I'm asking for is a way to keep all of the code that relates to
> >>> the model in one place and to invoke it from controllers.  That is if
> >>> I define 5 tables for the model I'd expect to write helper functions
> >>> to manipulate all 5 tables and not to have the controller know the
> >>> intimate details of the model.  That's the concept behind Object
> >>> Orientated programming isn't it?  Objects are black boxes to other
> >>> objects other than their public facing interface.
>
> >> Right - but DAL is just a Data abstraction layer (i.e. an SQL adapter,
> >> if you will), not an ORM (i.e. there's not the level of object-
> >> oriented abstraction that you would expect w/ an orm - it's lower
> >> level)
>
> >> So in web2py, with DAL you have knowledge of your table layout
> >> (without direct knowledge / need for the specific back ends SQL).
>
> >> You'll also find that forms, and validators are coupled to table
> >> structure, so if / as you try to abstract away from table definitions,
> >> you will run into this.
>
> >> I'm sure others will add more comments...
>
> >>> On Fri, Jun 4, 2010 at 8:56 AM, Yarko Tymciurak
>
> >>> <[email protected]> wrote:
>
> >>> > On Jun 4, 10:43 am, Doug Warren <[email protected]> wrote:
> >>> >> Traditionally when I've written MVC style applications, the model
> >>> >> would contain not only the data representing the objects but also the
> >>> >> data for manipulating the objects.  I'm not sure how that same
> >>> >> relation applies to web2py.
>
> >>> >> If I have a model that defines 4-5 tables, 2 of them are just foreign
> >>> >> key lookups, and creating a new object involves inserting data into 3
> >>> >> of the tables, it seems that I would want a create_object method in my
> >>> >> model file.
>
> >>> >> So I write something like:
>
> >>> >> def create_object(owner_id=None, template=None):
> >>> >>     # Some sanity checking on the above
> >>> >>     new_object = db.objects.insert(template_id=template.id, 
> >>> >> person_id=owner_id)
>
> >>> >>     widgets = db.template_widget(db.template_widget.thingy_template_id
> >>> >> == template.id).select()
> >>> >>     for widget in widgets: db.thingy_widget.insert(widget_id =
> >>> >> widget.id, thingy_id = new_object)
>
> >>> >>     whatchymacallits =
> >>> >> db.template_whatchymacallit(db.template_whatchymacallit.thingy_template_id
> >>> >> == template.id).select()
> >>> >>     for whatchymacallit in whatchymacallits:
> >>> >> db.thingy_whatchymacallit.insert(whatchymacallit_id =
> >>> >> whatchymacallit.id, thingy_id = new_object)
>
> >>> >>     return new_object
>
> >>> >> and place that into my db.py.  Now the controller has a function like:
> >>> >> def create():
> >>> >>     form = SQLFORM.factory( Field('template',
> >>> >> requires=IS_IN_SET(__get_templates())))
> >>> >>     if form.accepts(request.vars, session):
> >>> >>         foo = db.create_object(owner_id=auth.auth_id,
> >>> >> template_name=form.vars.template)
> >>> >>         response.flash = "Created"
> >>> >>     elif form.errors:
> >>> >>         response.flash = "Error (hacker)"
>
> >>> >> Well db is referring to the DAL db not the db.py, from db import
> >>> >> create_object gives a name not found error, so I'm at a loss as to how
> >>> >> to define functions that work upon the model and can be invoked from
> >>> >> one or more controllers.
>
> >>> > I'm not sure what exactly you are saying here - but to import, use
> >>> > local_import()
> >>> > (seehttp://www.web2py.com/book/default/section/4/18?search=local_import)
>
> >>> > BUT before you do, here is some background:
>
> >>> > When a request comes into web2py,   here's what happens (roughly):
>
> >>> > web2py parses the request url, and sets up an environment to call the
> >>> > appropriate application / controller / function;
> >>> > Part of that setup involves running all the files in your app's  model
> >>> >folder(so that db connections, table definitions, etc. are all "there
> >>> > for you");
>
> >>> > This means you can put your files in the modelsfolder, and they will
> >>> > be run (defined) before the call to your controller.
>
> >>> > Then, your controller / function is called.
>
> >>> > local_import will pull in definitions /modulesfrom your
> >>> > application'smodulesfolder, but you can (for development certainly)
> >>> > just put your file in your modelsfolder.
> >>> > When you really want to reduce what gets run at _each_ request, you
> >>> > might want to look at what to move tomodules, so that you're only
> >>> > pulling in those files when needed.
>
> >>> > As for db - DAL:   db is the "global" and "default"  name for the db
> >>> > connection string (it is so named and setup in the default models/
> >>> > db.py file).   You can change the name of this variable as you like
> >>> > (or change your imports).
>
> >>> > Hope this at least helps point you out of the forrest.
>
> >>> > Regards,
> >>> > - Yarko
> >>> >> Are there any non-trivial example
> >>> >> applications for web2py?  Most of the ones that I have seen assumes
> >>> >> that all data you need in thedatabasecan be supplied from a form and
> >>> >> that's not the case I run into over and over again.

Reply via email to