48 | | == Sahana3 Framework == |
49 | | We have built an S3 framework as a higher level of abstraction on top of T2.[[BR]] |
50 | | This should be used by modules where possible, but if more power is needed then drop down a level of two (to T2, to base Web2Py or to raw Python). |
51 | | |
52 | | T2 is used for: |
53 | | * [wiki:DeveloperGuidelinesAuthenticationAccess AAA] |
54 | | * simplified [wiki:DeveloperGuidelinesCreateReadUpdateDelete CRUD] |
55 | | * Conflict Detection) |
56 | | We extend the T2 class in {{{modules/sahana.py}}} |
57 | | |
58 | | Populate the side navigation Menus by adding this to each controller: |
59 | | {{{ |
60 | | module='module' |
61 | | # Current Module (for sidebar title) |
62 | | module_name=db(db.module.name==module).select()[0].name_nice |
63 | | # List Modules (from which to build Menu of Modules) |
64 | | modules=db(db.module.enabled=='Yes').select(db.module.ALL,orderby=db.module.menu_priority) |
65 | | # List Options (from which to build Menu for this Module) |
66 | | options=db(db['%s_menu_option' % module].enabled=='Yes').select(db['%s_menu_option' % module].ALL,orderby=db['%s_menu_option' % module].priority) |
67 | | }}} |
68 | | |
69 | | Each function needs to return these values to the view: |
70 | | return dict(module_name=module_name,modules=modules,options=options) |
71 | | |
72 | | List output can be made more functional by this .represent 'widget': |
73 | | {{{ |
74 | | def shn_list_item(table,resource,action,display='table.name',extra=None): |
75 | | if extra: |
76 | | items=DIV(TR(TD(A(eval(display),_href=t2.action(resource,[action,table.id]))),TD(eval(extra)))) |
77 | | else: |
78 | | items=DIV(A(eval(display),_href=t2.action(resource,[action,table.id]))) |
79 | | return DIV(*items) |
80 | | }}} |
81 | | You can use it in {{{models/module.py}}} like: |
82 | | {{{ |
83 | | db.or_organisation.represent=lambda table:shn_list_item(table,resource='organisation',action='display') |
84 | | db.person.represent=lambda table:shn_list_item(table,resource='person',action='display',display='table.full_name') |
85 | | db.gis_projection.represent=lambda table:shn_list_item(table,resource='projection',action='display',extra='table.epsg') |
86 | | }}} |
87 | | |
88 | | Form labels can be set in a translatable manner using: |
89 | | {{{db.table.field.label=T("label")}}} |
90 | | |
91 | | Form field can be made to use a TEXTAREA by marking the field as being type 'text': |
92 | | {{{SQLField('field','text'),}}} |
93 | | |
94 | | Form field can be made to use a SELECT dropdown by setting the field as a lookup to another table...linked to the 'uuid' field to allow [wiki:DeveloperGuidelinesDatabaseSynchronization Database Synchronization], but displaying a more user-friendly field (such as 'name'): |
95 | | {{{ |
96 | | SQLField('field',length=64), |
97 | | |
98 | | db.table.field.requires=IS_NULL_OR(IS_IN_DB(db,'othertable.uuid','othertable.name')) |
99 | | }}} |
100 | | |
101 | | Form field being required can be marked using: |
102 | | {{{db.table.field.comment=SPAN("*",_class="req")}}} |
103 | | |
104 | | Help for a form field can be set using: |
105 | | {{{A(SPAN("[Help]"),_class="popupLink",_id="tooltip",_title=T("Help Title|This is what this field is for."))}}} |
106 | | |
107 | | Different Flash styles can be set via: |
108 | | {{{ |
109 | | session.error=T("Unsupported format!") |
110 | | redirect(URL(r=request,f=resource)) |
111 | | }}} |
112 | | or (in a Multiple Table form.accepts): |
113 | | {{{ |
114 | | response.error=T("Form invalid!") |
115 | | }}} |
116 | | Supported styles are: |
117 | | * .warning |
118 | | * .error |
119 | | * .information |
120 | | * .confirmation (Standard T2 Flash messages are usually of this sort so we class them in the same way) |
121 | | |
122 | | === jQuery Widgets === |
123 | | DeveloperGuidelinesDeletableList |
124 | | |
125 | | === Options fields === |
126 | | Sahana2 has a generic 'field_options' table for storing Options fields. |
127 | | |
128 | | Sahana3 uses a separate table for each lookup list. |
129 | | |
130 | | === Conflict Detection === |
131 | | Sahana is a multi-user system so there is a potential for multiple users to be editing the same record at once.[[BR]] |
132 | | We use T2 to handle this for us. |
133 | | |
134 | | Add this field to each table which needs protecting (in {{{models/db.py}}}): |
135 | | {{{ |
136 | | SQLField('modified_on','datetime'), # Used by T2 to do edit conflict-detection |
137 | | }}} |
138 | | |
139 | | This field is also used in [wiki:DeveloperGuidelinesDatabaseSynchronization Database Synchronization] |
140 | | |
| 47 | * [wiki:DeveloperGuidelinesSahana3Framework Sahana3 Framework] |
| 48 | * [wiki:DeveloperGuidelinesSahana2Migration Help for Sahana2 Developers] |