DeveloperGuidelines == How to add a new module? == Copy an existing module, paste & edit. Good modules to look at to start with are or & cr as these are simplest & standard. === Model === Add module to db.module: * http://127.0.0.1:8000/sahana/appadmin/select/db?query=db.module.id%3E0 This makes it visible on the front page & the left-hand navigation menu Create a file {{{/models/module.py}}} This needs a table to store the module's menu options in: {{{ module='name' # Menu Options db.define_table('%s_menu_option' % module, SQLField('name'), SQLField('function'), SQLField('description',length=256), SQLField('priority','integer'), SQLField('enabled','boolean',default='True')) db['%s_menu_option' % module].name.requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB(db,'%s_menu_option.name' % module)] db['%s_menu_option' % module].name.requires=IS_NOT_EMPTY() db['%s_menu_option' % module].priority.requires=[IS_NOT_EMPTY(),IS_NOT_IN_DB(db,'%s_menu_option.priority' % module)] }}} Populate this table with the functions that you wish to expose to the module's front page & left-hand navigation bar: {{{ if not len(db().select(db['%s' % table].ALL)): db[table].insert( name="Home", function="index", priority=0, description="Home", enabled='True' ) db[table].insert( name="Add Vehicle", function="vehicle/create", priority=1, description="Add a vehicle to the database", enabled='True' ) db[table].insert( name="List Vehicles", function="vehicle", priority=2, description="List information of all vehicles", enabled='True' ) db[table].insert( name="Search Vehicles", function="vehicle/search", priority=3, description="List information of all vehicles", enabled='True' ) }}} Add additional tables to this file, as-required for your resources.[[BR]] To avoid namespace clashes, use the format: {{{db.module_table}}} e.g. if building a Vehicle Management System, create db.veh_vehicle: {{{ module='veh' resource='vehicle' table=module+'_'+resource db.define_table(table,timestamp,uuidstamp, SQLField('name')) s3.crud_fields[table]=['name'] db[table].exposes=s3.crud_fields[table] db[table].uuid.requires=IS_NOT_IN_DB(db,'%s.uuid' % table) db.veh_vehicle.name.requires=IS_NOT_EMPTY() db.veh_vehicle.name.comment=SPAN("*",_class="req") }}} Also add the messages for your resources: {{{ 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') 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') crud_strings[table]=Storage(title_create=title_create, title_display=title_display, title_list=title_list, title_update=title_update, subtitle_create=subtitle_create, subtitle_list=subtitle_list, label_list_button=label_list_button, label_create_button=label_create_button, msg_record_created=msg_record_created, msg_record_modified=msg_record_modified, msg_record_deleted=msg_record_deleted, msg_list_empty=msg_list_empty) }}} === Controller === Create a file: {{{/controllers/module.py}}} Add the S3 framework functions: {{{ module='veh' # Current Module (for sidebar title) module_name=db(db.s3_module.name==module).select()[0].name_nice # List Modules (from which to build Menu of Modules) modules=db(db.s3_module.enabled=='Yes').select(db.s3_module.ALL,orderby=db.s3_module.priority) # List Options (from which to build Menu for this Module) options=db(db['%s_menu_option' % module].enabled=='Yes').select(db['%s_menu_option' % module].ALL,orderby=db['%s_menu_option' % module].priority) }}} Add CRUD functions for your tables: {{{ def vehicle(): "RESTful CRUD controller" return shn_rest_controller(module,'vehicle') }}} Manual method for if/when you need more control: DeveloperGuidelinesCreateReadUpdateDelete === Views === Add HTML templates for any custom functions: {{{/views/module/function.html}}} NB Only {{{index.html}}} is required to start with since the RESTful controller normally re-uses standard views.[[BR]] If Custom Views are wanted they are detected automatically if files are found in {{{/views/module/resource_method.html}}} DeveloperGuidelines