If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

web2py and modules

Python modules can be stored in web2py/application/<yourapp>/modules folder.

Inside that folder you can put your own modules or any Python Package or module you want to be isolated from the rest of web2py environment.


Basic App Structure

A simple web2py app consists in

  • controllers/default.py - Here you decide the app flow and user interaction
  • views/default/<action>.extension - Here you design your interfaces
  • models/ - Models are like scripts, .py files here are executed alphabetically on every request
  • modules/ - Your logic code, libs, modules and packages


Contact application


# -*- coding: utf-8 -*-

response.generic_patterns = ['*']
from gluon.custom_import import track_changes

It is simply for web2py allow us to use generic views, and also for reload our modules automatically when detect changes.



from contact import Contact

def index():
    contact = Contact()
    form = contact.form(formstyle='divs')
    rows = contact.load('all', limitby=(0, 25))
    return dict(form=form, rows=rows)

The above controller action will import a Contact class and instantiate it, also will create form using the Contact form method and fetch records using load method, finally it will return a dict to be rendered in the view



{{extend "layout.html"}}

<h1> insert a new contact</h1>

    {{for row in rows:}}
        {{="%(name)s - %(email)s - %(phone)s" % row}}


modules/__init__.py - Must be there at least as an empty file



#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gluon import current
from gluon.dal import DAL, Field
from gluon.sqlhtml import SQLFORM
from gluon.validators import IS_NOT_EMPTY, IS_EMAIL, IS_LENGTH

class Contact(object):
    """Build a Contact object"""

    def __init__(self):
        self.db = DAL("sqlite://mydb.sqlite")
        self.session = current.session
        self.request = current.request
        self.response = current.response
        self.cache = current.cache

    def define_table(self):
        self.contact = self.db.define_table("contact",

    def set_validators(self):
        self.contact.name.requires = IS_NOT_EMPTY()
        self.contact.email.requires = IS_EMAIL()
        self.contact.phone.requires = IS_LENGTH(14)

    def form(self, formstyle):
        return SQLFORM(self.contact, formstyle=formstyle).process()

    def load(self, scope, limitby=None):
        queries = {"all": self.contact.id>0,
                   "gmailers": self.contact.email.like("%gmail.com%")}
        return self.db(queries[scope]).select(limitby=limitby)


Thats it! smiley


The running app looks like this:


You can get the source packed app here


Related slices

Comments (5)

  • Login to post

  • 0
    chen 11 years ago



    I just tried ur example.  But I found that we actually dont need to import the model.


    If we add the import statement, it gives error in importing instead.

  • 0
    vegeta 12 years ago

    When I tried this and attempted to save the module, I got the error:

    "failed to reload module because:No module named xxx.modules.contact"

    Ideas on what this is?

  • 0
    rochacbruno 12 years ago

    That is just an example, for better result, it is nice to have a DataBase class to define db, it should use Singleton to insure only one db instance defined.

    replies (1)
    • mirko 10 years ago

      Hi Bruno, I really loved this slice but can you please show how to create such a DataBase class using Singleton ? Many thanks!

  • 0
    adesanto-asman-10337 12 years ago

    Hi Bruno, nice shared. But i've a question,

    Why In the module you've defined new DAL connection and not pass

    existing DAL connection in the __init__ of the module 

    or maybe using the gluon.current?


    replies (1)
    • andrew-willimott-10653 12 years ago

      Hi, not sure what you mean. Db is defined only once in the __init__. But what if you had referenced two classes in your controller. Does it mean there is a dal connection for each table ? Is that what you meant?

Hosting graciously provided by:
Python Anywhere