Customization
Sahana Eden is developed using Python and JavaScript. However, amazing as it may sound, simple customization can be done without any knowledge of either programming language. In fact there is just a single concept which is essential to understand before diving in: whitespace matters.
Why Whitespace Matters
Unlike many programming languages, Python code is sensitive to whitespace. To avoid bad results as an impact of this sensitivity, make sure that you indent the code in .py files properly. This is easiest if you configure your text editor to replace Tabs with 4 spaces:

The screenshot is from Notepad++, a recommended editor on Windows, where you can find this by going to Settings -> Preferences... -> Language Menu/Tab Settings -> Tab Settings (group)
Which file do I edit?
Sahana Eden runs as a Web2Py application. The code is in the folder:
web2py/applications/eden
Inside that folder are folders for Models (define the data structure), Controllers (provide URLs to enable access to the data) & Views (HTML templates).
Each module within Sahana Eden will normally consist of one of each of these files:
- Model: modules/eden/modulename.py
- Controller: controllers/modulename.py
- View: views/modulename/index.html
In order to know which file to edit in order to change a particular function, you need to look at the URL. The Web2Py web framework maps URLs as follows:
http://host/application/controller/function
So, if you want to edit the Home page with the URL:
http://host/eden/default/index
This implies that you should look at the file eden/controllers/default.py and the index function within it which can be found by searching for the function title "def index():"
Tip: Sahana Eden makes heavy use of integrated resource controllers so the typical mapping is:
http://host/eden/module/resource
The resource refers to a table with the name module_resource in the file modules/eden/<module>.py
Index Pages
One of the common changes that needs to be made is modifying the main home page, individual module home pages and the Contact/About pages.
Some of these customizations can be done in pure HTML by editing the View files. For example, you can edit the contact page at URL /eden/default/contact by editing the file: views/default/contact.html
This is a normal HTML page other than the part(s) inside double curly braces {{...}} which indicate Python code.
{{extend "layout.html"}}
This part should not be edited as it loads the generic page layout from views/layout.html.
Most pages, such as the main home page, include the results of Python code executed in the controller file. This is executed before the view template is parsed and dynamically generates content which is inserted in the curly brackets inside the HTML. The controller file for the main home page is controllers/default.py
The simple way to start customizing this page is to ignore some or all of this dynamic content and replace it with simple HTML content in the view template: views/default/index.html
Tip: Sahana Eden doesn't make use of many custom views – normally the generic view templates within the views/ folder are used. Modifications are made by configuration in the Model and Controller files. However it is possible to use custom views by adding these into views/modulename/
Debug mode
Changes made to files in the modules/ folder normally require a restart of Web2Py to see the changes. For the model files held in modules/eden/ this can be avoided by running in 'debug' mode. It is recommended that developers enable debug mode with the following setting:
models/000_config.pydeployment_settings.debug = True
Edit a Field Label
This can be done by editing the 'label' attribute in the field properties within the model.
Example:
Change the label 'Donation Phone #' in the form at URL: /eden/org/organisation/create
The relevant code can be found in modules/eden/org.py:
tablename = "org_organisation"
table = define_table(tablename,
Field("donation_phone", label = T("Donation Phone Number"),
For consistency, you should also edit the heading of the help tooltip, and maybe the body, if the meaning is being changed. This is found in the 'comment' attribute:
comment = DIV(_class="tooltip",
_title="%s|%s" % (T("Donation Phone Number"),
T("Phone number to donate to this organization's relief efforts.")))),

Tip: The strings are internationalized by wrapping them inside T(). If you change the labels then you need to update any translation files that you are using, even if the translation remains the same.
Hide a Field
It is common to want to hide a field to simplify a form to allow efficient collection of the data that you need. Hiding a field is safer than removing it completely from the database as it eases upgrades by eliminating the need for database migration.
Example:
Hide the 'type' field from the form at URL: /eden/org/office/create
You should look at modules/eden/org.py and add readable=False and writable=False to the field properties:
tablename = "org_office"
table = define_table(tablename,
...
Field("type", "integer",
readable=False,
writable=False,
label=T("Type")),
Tip: Python variables are case-sensitive, as are the boolean values 'True' and 'False'.
Add a New Field
If you need to collect extra data for an existing resource, then it is simple and safe to add an extra field to the model for that table.
Example:
Add the ability to store a Facebook page for Organizations.
Look at modules/eden/org.py and add the new field to:
tablename = "org_organisation"
table = define_table(tablename,
...
Field("facebook", label=T("Facebook Page")),

Tip: Be careful to add trailing commas to each line as this is a common source of errors.
Edit the Menus
If you wish to edit the left (second-level) menus (e.g. relabeling, reordering or hiding entries) then edit the file modules/eden/menus.py. Each module has its own menu defined as a function there.
Example:
In the Organization Registry Module, re-name 'Offices' as 'Venues' and hide the 'Search' option:
def org(self):
""" ORG / Organization Registry """
return M(c="org")(
M("Organizations", f="organisation")(
M("New", m="create"),
M("List All"),
M("Search", m="search"),
M("Import", m="import")
),
M("Venues", f="office")(
M("New", m="create"),
M("List All"),
#M("Search", m="search"),
M("Import", m="import")
),
)
You can see this change in the Organization Registry Module at URL: /eden/org

Tip: The # character comments out the text after it on that line so that Python will ignore it.





