Changes between Version 24 and Version 25 of BluePrintRESTImplementation


Ignore:
Timestamp:
01/04/09 18:15:01 (13 years ago)
Author:
Fran Boon
Comment:

Update to current. Reword to target Module Writers

Legend:

Unmodified
Added
Removed
Modified
  • BluePrintRESTImplementation

    v24 v25  
    22
    33== Model ==
    4 {{{models/module.py}}}
     4This is how Module writers need to add tables to their {{{models/module.py}}}:
    55{{{
    66resource='shelter'
    7 single=resource.capitalize()
    8 # NB May need manual fixing!
    9 plural=single+'s'
    10 title_create=T('Add %s' % single)
    11 title_display=T('%s Details' % single)
    12 title_list=T('List %s' % plural)
    13 title_update=T('Edit %s' % single)
    14 subtitle_create=T('Add New %s' % single)
    15 subtitle_list=T('%s' % plural)
    16 label_list_button=T('List %s' % plural)
    17 label_create_button=T('Add %s' % single)
    18 msg_record_created=T('%s added' % single)
    19 msg_record_modified=T('%s updated' % single)
    20 msg_record_deleted=T('%s deleted' % single)
    21 msg_list_empty=T('No %s currently registered' % plural)
     7table=module+'_'+resource
     8db.define_table(table,
     9                SQLField('modified_on','datetime',default=now),
     10                SQLField('uuid',length=64,default=uuid.uuid4()),
     11                SQLField('name'))
     12# NB Beware of lambdas & %s substitution as they get evaluated when called, not when defined!
     13db['%s' % table].represent=lambda table:shn_list_item(table,resource='shelter',action='display')
     14title_create=T('Add Shelter')
     15title_display=T('Shelter Details')
     16title_list=T('List Shelters')
     17title_update=T('Edit Shelter')
     18subtitle_create=T('Add New Shelter')
     19subtitle_list=T('Shelters')
     20label_list_button=T('List Shelters')
     21label_create_button=T('Add Shelter')
     22msg_record_created=T('Shelter added')
     23msg_record_modified=T('Shelter updated')
     24msg_record_deleted=T('Shelter deleted')
     25msg_list_empty=T('No Shelters currently registered')
    2226exec('crud_strings.%s=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)' % resource)
    2327}}}
    2428
    25 {{{models/_db.py}}}
    26 {{{
     29This is the supporting material in {{{models/_db.py}}}:
     30{{{
     31from gluon.storage import Storage
     32crud_strings=Storage()
     33
    2734def shn_crud_strings_lookup(resource):
    28     "Look up CRUD strings for a given resource."
     35    "Look up CRUD strings for a given resource based on the definitions in models/module.py."
    2936    return getattr(crud_strings,'%s' % resource)
    3037
     
    3643    Authentication required for Create/Update/Delete.
    3744   
     45    Supported Representations:
     46        HTML is the default (including full Layout)
     47        PLAIN is HTML with no layout
     48         - can be inserted into DIVs via AJAX calls
     49         - can be useful for clients on low-bandwidth or small screen sizes
     50        JSON
     51         - read-only for now
     52
    3853    ToDo:
    3954        Alternate Representations
     55            JSON create/update
     56            SMS,CSV,XML,PDF
    4057        Search method
    4158        Customisable Security Policy
     
    4360   
    4461    table=db['%s_%s' % (module,resource)]
    45    
    4662    crud_strings=shn_crud_strings_lookup(resource)
    47 
     63   
     64    # Which representation should output be in?
     65    if request.vars.format:
     66        representation=str.lower(request.vars.format)
     67    else:
     68        # Default to HTML
     69        representation="html"
     70   
    4871    if len(request.args)==0:
    4972        # No arguments => default to list (or list_create if logged_in)
    50         list=t2.itemize(table)
    51         if list=="No data":
    52             list=crud_strings.msg_list_empty
    53         title=crud_strings.title_list
    54         subtitle=crud_strings.subtitle_list
    55         if t2.logged_in:
    56             form=t2.create(table)
    57             response.view='list_create.html'
    58             addtitle=crud_strings.subtitle_create
    59             return dict(module_name=module_name,modules=modules,options=options,list=list,form=form,title=title,subtitle=subtitle,addtitle=addtitle)
     73        if representation=="html":
     74            list=t2.itemize(table)
     75            if list=="No data":
     76                list=crud_strings.msg_list_empty
     77            title=crud_strings.title_list
     78            subtitle=crud_strings.subtitle_list
     79            if t2.logged_in:
     80                form=t2.create(table)
     81                response.view='list_create.html'
     82                addtitle=crud_strings.subtitle_create
     83                return dict(module_name=module_name,modules=modules,options=options,list=list,form=form,title=title,subtitle=subtitle,addtitle=addtitle)
     84            else:
     85                add_btn=A(crud_strings.label_create_button,_href=t2.action(resource,'create'))
     86                response.view='list.html'
     87                return dict(module_name=module_name,modules=modules,options=options,list=list,title=title,subtitle=subtitle,add_btn=add_btn)
     88        elif representation=="plain":
     89            list=t2.itemize(table)
     90            response.view='plain.html'
     91            return dict(item=list)
     92        elif representation=="json":
     93            list=db().select(table.ALL).json()
     94            response.view='plain.html'
     95            return dict(item=list)
    6096        else:
    61             add_btn=A(crud_strings.label_create_button,_href=t2.action(resource,'create'))
    62             response.view='list.html'
    63             return dict(module_name=module_name,modules=modules,options=options,list=list,title=title,subtitle=subtitle,add_btn=add_btn)
    64            
     97            session.error=T("Unsupported format!")
     98            redirect(URL(r=request,f=resource))
    6599    else:
    66         method=request.args[0]
     100        method=str.lower(request.args[0])
    67101        if request.args[0].isdigit():
    68102            # 1st argument is ID not method => display.
    69             # Default format (representation) is full HTML page
    70             item=t2.display(table)
    71             response.view='display.html'
    72             title=crud_strings.title_display
    73             edit=A(T("Edit"),_href=t2.action(resource,['update',t2.id]))
    74             list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
    75             return dict(module_name=module_name,modules=modules,options=options,item=item,title=title,edit=edit,list_btn=list_btn)
     103            if representation=="html":
     104                item=t2.display(table)
     105                response.view='display.html'
     106                title=crud_strings.title_display
     107                edit=A(T("Edit"),_href=t2.action(resource,['update',t2.id]))
     108                delete=A(T("Delete"),_href=t2.action(resource,['delete',t2.id]))
     109                list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
     110                return dict(module_name=module_name,modules=modules,options=options,item=item,title=title,edit=edit,delete=delete,list_btn=list_btn)
     111            elif representation=="plain":
     112                item=t2.display(table)
     113                response.view='plain.html'
     114                return dict(item=item)
     115            elif representation=="json":
     116                item=db(table.id==t2.id).select(table.ALL).json()
     117                response.view='plain.html'
     118                return dict(item=item)
     119            else:
     120                session.error=T("Unsupported format!")
     121                redirect(URL(r=request,f=resource))
    76122        else:
    77123            if method=="create":
    78124                if t2.logged_in:
    79                     t2.messages.record_created=crud_strings.msg_record_created
    80                     form=t2.create(table)
    81                     response.view='create.html'
    82                     title=crud_strings.title_create
    83                     list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
    84                     return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
     125                    if representation=="html":
     126                        t2.messages.record_created=crud_strings.msg_record_created
     127                        form=t2.create(table)
     128                        response.view='create.html'
     129                        title=crud_strings.title_create
     130                        list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
     131                        return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
     132                    elif representation=="plain":
     133                        form=t2.create(table)
     134                        response.view='plain.html'
     135                        return dict(item=form)
     136                    elif representation=="json":
     137                        # ToDo
     138                        item='{"Status":"failed","Error":{"StatusCode":501,"Message":"JSON creates not yet supported!"}}'
     139                        response.view='plain.html'
     140                        return dict(item=item)
     141                    else:
     142                        session.error=T("Unsupported format!")
     143                        redirect(URL(r=request,f=resource))
    85144                else:
    86145                    t2.redirect('login',vars={'_destination':'%s/create' % resource})
     
    89148            elif method=="update":
    90149                if t2.logged_in:
    91                     t2.messages.record_modified=crud_strings.msg_record_modified
    92                     form=t2.update(table)
    93                     response.view='update.html'
    94                     title=crud_strings.title_update
    95                     list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
    96                     return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
     150                    if representation=="html":
     151                        t2.messages.record_modified=crud_strings.msg_record_modified
     152                        form=t2.update(table,deletable=False)
     153                        response.view='update.html'
     154                        title=crud_strings.title_update
     155                        list_btn=A(crud_strings.label_list_button,_href=t2.action(resource))
     156                        return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
     157                    elif representation=="plain":
     158                        form=t2.update(table,deletable=False)
     159                        response.view='plain.html'
     160                        return dict(item=form)
     161                    elif representation=="json":
     162                        # ToDo
     163                        item='{"Status":"failed","Error":{"StatusCode":501,"Message":"JSON updates not yet supported!"}}'
     164                        response.view='plain.html'
     165                        return dict(item=item)
     166                    else:
     167                        session.error=T("Unsupported format!")
     168                        redirect(URL(r=request,f=resource))
    97169                else:
    98170                    t2.redirect('login',vars={'_destination':'%s/update/%i' % (resource,t2.id)})
     
    101173                    t2.messages.record_deleted=crud_strings.msg_record_deleted
    102174                    t2.delete(table,next=resource)
    103                     return
    104175                else:
    105176                    t2.redirect('login',vars={'_destination':'%s/delete/%i' % (resource,t2.id)})
    106177            else:
    107                 # Unsupported method!
    108                 t2.redirect(resource)
    109 }}}
    110 
    111 Simplified module table:
    112 {{{
    113 resource='shelter'
    114 table=module+'_'+resource
    115 db.define_table(table,
    116                 SQLField('modified_on','datetime',default=now),
    117                 SQLField('uuid',length=64,default=uuid.uuid4()),
    118                 SQLField('name'))
    119 db['%s' % table].represent=lambda table:shn_list_item(table,resource='shelter',action='display')
    120 }}}
    121 NB Beware of lambdas & %s substitution as they get evaluated when called, not when defined!
     178                session.error=T("Unsupported method!")
     179                redirect(URL(r=request,f=resource))
     180}}}
    122181
    123182== Controller ==
     183If using a single table for a resource, Developers just need to add this to their Controllers to provide all necessary CRUD functions with support for multiple representations:
    124184{{{
    125185def shelter():
     
    129189
    130190== Views ==
     191If using a single table for a resource, Developers don't normally need to create any special views for CRUD. Default ones work fine.
     192
     193If needing to create custom views (e.g. GIS Layer currently) then can extend these to add extra information in a maintainable way.
    131194{{{create.html}}}
    132195{{{
    133 {{extend 'layout.html'}}
    134 
     196{extend 'layout.html'}}
    135197{{try:}}
    136198 {{=H2(title)}}
     
    142204 {{=form}}
    143205{{except:}}
     206  {{include}}
    144207{{pass}}
    145208</div>
     
    150213{{pass}}
    151214}}}
     215
    152216{{{display.html}}}
    153217{{{
    154218{{extend 'layout.html'}}
    155 
    156219{{try:}}
    157220 {{=H2(title)}}
     
    166229 {{=item}}
    167230{{except:}}
    168 {{pass}}
    169 </div>
     231  {{include}}
     232{{pass}}
     233</div>
     234{{try:}}
     235 {{=delete}}
     236{{except:}}
     237{{pass}}
    170238<p>&nbsp;</p>
    171239{{try:}}
     
    174242{{pass}}
    175243}}}
     244
    176245{{{list.html}}}
    177246{{{
    178247{{extend 'layout.html'}}
    179 
    180248{{try:}}
    181249 {{=H2(title)}}
     
    190258 {{=list}}
    191259{{except:}}
     260  {{include}}
    192261{{pass}}
    193262</div>
     
    198267{{pass}}
    199268}}}
     269
    200270{{{list_create.html}}}
    201271{{{
    202272{{extend 'layout.html'}}
    203 
    204273{{try:}}
    205274 {{=H2(title)}}
     
    229298{{include 'key.html'}}
    230299}}}
     300
    231301{{{update.html}}}
    232302{{{
     
    242312 {{=form}}
    243313{{except:}}
     314  {{include}}
    244315{{pass}}
    245316</div>
     
    250321{{pass}}
    251322}}}
     323
    252324{{{key.html}}}
    253325{{{
    254326<p><b>{{=T('Key')}}:</b><b class='red'> * </b> - {{=T('Fields tagged with a star')}} &#040;<span class='red'> * </span>&#041; {{=T('are mandatory and must be filled')}}.</p>
    255327}}}
     328
     329{{{plain.html}}}
     330{{{
     331{{=item}}
     332}}}