wiki:DeveloperGuidelinesNewModule

DeveloperGuidelines

How to add a new module

The Eden Book has a tutorial for adding a new module. However, it is simplified from the normal way modules are included in Eden. Especially, the model file differs. This page shows the structure of an Eden module, and deliberately omits details, which are described elsewhere.

Settings

Add your module to settings.modules in modules/templates/<template>/config.py if it is for a specific template.

Add it to modules/templates/default/config.py to provide an example of how your module should be entered in settings.modules.

Model

Create a file modules/s3db/<MODULE NAME>.py

Add an import statement to models/00_tables.py:

import s3db.<MODULE NAME>

For each major "resource" in your module, add a class that is a subclass of S3Model. The class must define a model() method that defines the tables for that resource. The class can define multiple tables, for other resources associated with the major resource. For instance, if you have a major resource representing a vehicle, you might want a table to represent types of vehicles, so users can add new types without changing the code. The main table for specific vehicles and the table for types can go in the same model class.

To avoid namespace clashes, use your module name as a prefix for table names. Follow with underscore and the name of the resource your table represents: <MODULE NAME>_<RESOURCE>. Resource names should be unique.

E.g. if building a Vehicle Management System with module name vms, with individual vehicles and vehicle types:

__all__ = ["S3VehicleModel",
           "vms_vehicle",
           "vms_vehicle_type",
          ]

class S3VehicleModel(S3Model):
    """
        Vehicle Management
    """

    names = ["vms_vehicle",
             "vms_vehicle_type",
            ]

    def model(self):

        T = current.T
        db = current.db

        tablename = "vms_vehicle_type"
        table = self.define_table(tablename,
                                  Field("name",
                                        requires = IS_NOT_EMPTY()
                                       ),
                                  *s3_meta_fields())

        self.crud_strings[tablename] = Storage(
            title_create = T("Add Vehicle Type"),
            title_display = T("Vehicle Type Details"),
            title_list = T("List Vehicle Types"),
            title_update = T("Edit Vehicle Type"),
            title_search = T("Search Vehicle Types"),
            subtitle_create = T("Add New Vehicle Type"),
            subtitle_list = T("Vehicle Types"),
            label_list_button = T("List Vehicle Types"),
            label_create_button = T("Add Vehicle Type"),
            label_delete_button = T("Delete Vehicle Type"),
            msg_record_created = T("Vehicle Type added"),
            msg_record_modified = T("Vehicle Type updated"),
            msg_record_deleted = T("Vehicle Type deleted"),
            msg_list_empty = T("No Vehicle Types currently defined"))

        tablename = "vms_vehicle"
        represent = S3Represent(lookup=tablename)
        table = self.define_table(tablename,
                                  Field("name",
                                        requires = IS_NOT_EMPTY()
                                       ),
                                  Field("type",
                                        requires=IS_ONE_OF(db,
                                                           "vms_vehicle_type.id",
                                                           represent),
                                       )
                                  *s3_meta_fields())

        crud_strings[tablename] = Storage(
            title_create = T("Add Vehicle"),
            title_display = T("Vehicle Details"),
            title_list = T("List Vehicles"),
            title_update = T("Edit Vehicle"),
            title_search = T("Search Vehicles"),
            subtitle_create = T("Add New Vehicle"),
            subtitle_list = T("Vehicles"),
            label_list_button = T("List Vehicles"),
            label_create_button = T("Add Vehicle"),
            label_delete_button = T("Delete Vehicle"),
            msg_record_created = T("Vehicle added"),
            msg_record_modified = T("Vehicle updated"),
            msg_record_deleted = T("Vehicle deleted"),
            msg_list_empty = T("No Vehicles currently registered"))

Controller

Create a file: controllers/<MODULE NAME>.py

Add controller functions for your resources, and an index() function for your controller's landing page:

module = request.controller

if not settings.has_module(module):
    raise HTTP(404, body="Module disabled: %s" % module)

def index():
    """ Module Home Page """

    module_name = settings.modules[module].name_nice
    response.title = module_name

    return dict(module_name=module_name)

def vehicle():
    """ RESTful CRUD controller """

    return s3_rest_controller()

Additional options are described here: s3_rest_controller

A basic navigation menu will be constructed by default for each view page, and a menu item for the module's landing page will be added to the top menu bar or its More menu.

For custom menus, see Menus

Views

Create a directory for your view pages: views/<MODULE NAME>

Within that directory, add HTML templates for index.html and any custom views. A simple index.html is:

{{extend "layout.html"}}
<div id='home'>
{{=H2(T(module_name))}}
<p>
{{=T("Manage Vehicles")}}
</p>
</div>

NB Only index.html is required to start with since the RESTful controller normally re-uses standard views.

A custom view for a resource named <MODULE NAME>_<RESOURCE> will be found automatically if the view page is named <RESOURCE>_<METHOD>.html


DeveloperGuidelines DeveloperGuidelines

Last modified 10 years ago Last modified on 01/05/15 14:59:33
Note: See TracWiki for help on using the wiki.