Changes between Version 38 and Version 39 of BluePrintRESTImplementation


Ignore:
Timestamp:
04/29/09 21:42:41 (16 years ago)
Author:
Fran Boon
Comment:

Link to db.py (too much effort to keep updating this & old data is bad)

Legend:

Unmodified
Added
Removed
Modified
  • BluePrintRESTImplementation

    v38 v39  
    3030}}}
    3131
    32 This is the supporting material in {{{models/__db.py}}}:
    33 {{{
    34 from gluon.storage import Storage
    35 # Keep all S3 framework-level elements stored off here, so as to avoid polluting global namespace & to make it clear which part of the framework is being interacted with
    36 s3=Storage()
    37 s3.crud_fields=Storage()
    38 s3.crud_strings=Storage()
    39 
    40 def shn_crud_strings_lookup(resource):
    41     "Look up CRUD strings for a given resource based on the definitions in models/module.py."
    42     return getattr(s3.crud_strings,'%s' % resource)
    43 
    44 def import_csv(table,file):
    45     "Import CSV file into Database. Comes from appadmin.py"
    46     import csv
    47     reader = csv.reader(file)
    48     colnames=None
    49     for line in reader:
    50         if not colnames:
    51             colnames=[x[x.find('.')+1:] for x in line]
    52             c=[i for i in range(len(line)) if colnames[i]!='id']           
    53         else:
    54             items=[(colnames[i],line[i]) for i in c]
    55             table.insert(**dict(items))
    56 
    57 def import_json(table,file):
    58     "Import JSON into Database."
    59     import gluon.contrib.simplejson as sj
    60     reader=sj.loads(file)
    61     # ToDo
    62     # Get column names
    63     # Insert records
    64     #table.insert(**dict(items))
    65     return
    66            
    67 def shn_rest_controller(module,resource,deletable=True,listadd=True,extra=None):
    68     """
    69     RESTlike controller function.
    70    
    71     Provides CRUD operations for the given module/resource.
    72     Optional parameters:
    73     deletable=False: don't provide visible options for deletion
    74     listadd=False: don't provide an add form in the list view
    75     extra='field': extra field to display in the list view
    76    
    77     Anonymous users can Read.
    78     Authentication required for Create/Update/Delete.
    79    
    80     Auditing options for Read &/or Write.
    81    
    82     Supported Representations:
    83         HTML is the default (including full Layout)
    84         PLAIN is HTML with no layout
    85          - can be inserted into DIVs via AJAX calls
    86          - can be useful for clients on low-bandwidth or small screen sizes
    87         JSON
    88          - read-only for now
    89         CSV (useful for synchronization)
    90          - List/Display/Create for now
    91         AJAX (designed to be run asynchronously to refresh page elements)
    92 
    93     ToDo:
    94         Alternate Representations
    95             JSON create/update
    96             CSV update
    97             SMS,XML,PDF,LDIF
    98         Customisable Security Policy
    99     """
    100    
    101     _table='%s_%s' % (module,resource)
    102     table=db[_table]
    103     if resource=='setting':
    104         s3.crud_strings=shn_crud_strings_lookup(resource)
    105     else:
    106         s3.crud_strings=shn_crud_strings_lookup(table)
    107    
    108     # Which representation should output be in?
    109     if request.vars.format:
    110         representation=str.lower(request.vars.format)
    111     else:
    112         # Default to HTML
    113         representation="html"
    114    
    115     # Is user logged-in?
    116     logged_in = auth.is_logged_in()
    117    
    118     if len(request.args)==0:
    119         # No arguments => default to List (or list_create if logged_in)
    120         if session.s3.audit_read:
    121             db.s3_audit.insert(
    122                 person=auth.user.id,
    123                 operation='list',
    124                 module=request.controller,
    125                 resource=resource,
    126                 old_value='',
    127                 new_value=''
    128             )
    129         if representation=="html":
    130             shn_represent(table,resource,deletable,extra)
    131             list=t2.itemize(table)
    132             if not list:
    133                 list=s3.crud_strings.msg_list_empty
    134             title=s3.crud_strings.title_list
    135             subtitle=s3.crud_strings.subtitle_list
    136             if logged_in and listadd:
    137                 # Display the Add form below List
    138                 if deletable:
    139                     # Add extra column header to explain the checkboxes
    140                     if isinstance(list,TABLE):
    141                         list.insert(0,TR('',B('Delete?')))
    142                 form=t2.create(table)
    143                 # Check for presence of Custom View
    144                 custom_view='%s_list_create.html' % resource
    145                 _custom_view=os.path.join(request.folder,'views',module,custom_view)
    146                 if os.path.exists(_custom_view):
    147                     response.view=module+'/'+custom_view
    148                 else:
    149                     response.view='list_create.html'
    150                 addtitle=s3.crud_strings.subtitle_create
    151                 return dict(module_name=module_name,modules=modules,options=options,list=list,form=form,title=title,subtitle=subtitle,addtitle=addtitle)
    152             else:
    153                 # List only
    154                 if listadd:
    155                     add_btn=A(s3.crud_strings.label_create_button,_href=t2.action(resource,'create'),_id='add-btn')
    156                 else:
    157                     add_btn=''
    158                 # Check for presence of Custom View
    159                 custom_view='%s_list.html' % resource
    160                 _custom_view=os.path.join(request.folder,'views',module,custom_view)
    161                 if os.path.exists(_custom_view):
    162                     response.view=module+'/'+custom_view
    163                 else:
    164                     response.view='list.html'
    165                 return dict(module_name=module_name,modules=modules,options=options,list=list,title=title,subtitle=subtitle,add_btn=add_btn)
    166         elif representation=="ajax":
    167             shn_represent(table,resource,deletable,extra)
    168             list=t2.itemize(table)
    169             if not list:
    170                 list=s3.crud_strings.msg_list_empty
    171             if deletable:
    172                 # Add extra column header to explain the checkboxes
    173                 if isinstance(list,TABLE):
    174                     list.insert(0,TR('',B('Delete?')))
    175             response.view='plain.html'
    176             return dict(item=list)
    177         elif representation=="plain":
    178             list=t2.itemize(table)
    179             response.view='plain.html'
    180             return dict(item=list)
    181         elif representation=="json":
    182             list=db().select(table.ALL).json()
    183             response.view='plain.html'
    184             return dict(item=list)
    185         elif representation=="csv":
    186             import gluon.contenttype
    187             response.headers['Content-Type']=gluon.contenttype.contenttype('.csv')
    188             query=db[table].id>0
    189             response.headers['Content-disposition']="attachment; filename=%s_%s_list.csv" % (request.env.server_name,resource)
    190             return str(db(query).select())
    191         else:
    192             session.error=T("Unsupported format!")
    193             redirect(URL(r=request))
    194     else:
    195         method=str.lower(request.args[0])
    196         if request.args[0].isdigit():
    197             # 1st argument is ID not method => Display.
    198             if session.s3.audit_read:
    199                 db.s3_audit.insert(
    200                     person=auth.user.id,
    201                     operation='read',
    202                     representation=representation,
    203                     module=request.controller,
    204                     resource=resource,
    205                     record=t2.id,
    206                     old_value='',
    207                     new_value=''
    208                 )
    209             if representation=="html":
    210                 try:
    211                     db[table].displays=s3.crud_fields[table]
    212                 except:
    213                     pass
    214                 item=t2.display(table)
    215                 # Check for presence of Custom View
    216                 custom_view='%s_display.html' % resource
    217                 _custom_view=os.path.join(request.folder,'views',module,custom_view)
    218                 if os.path.exists(_custom_view):
    219                     response.view=module+'/'+custom_view
    220                 else:
    221                     response.view='display.html'
    222                 title=s3.crud_strings.title_display
    223                 edit=A(T("Edit"),_href=t2.action(resource,['update',t2.id]),_id='edit-btn')
    224                 if deletable:
    225                     delete=A(T("Delete"),_href=t2.action(resource,['delete',t2.id]),_id='delete-btn')
    226                 else:
    227                     delete=''
    228                 list_btn=A(s3.crud_strings.label_list_button,_href=t2.action(resource),_id='list-btn')
    229                 return dict(module_name=module_name,modules=modules,options=options,item=item,title=title,edit=edit,delete=delete,list_btn=list_btn)
    230             elif representation=="plain":
    231                 item=t2.display(table)
    232                 response.view='plain.html'
    233                 return dict(item=item)
    234             elif representation=="json":
    235                 item=db(table.id==t2.id).select(table.ALL).json()
    236                 response.view='plain.html'
    237                 return dict(item=item)
    238             elif representation=="csv":
    239                 import gluon.contenttype
    240                 response.headers['Content-Type']=gluon.contenttype.contenttype('.csv')
    241                 query=db[table].id==t2.id
    242                 response.headers['Content-disposition']="attachment; filename=%s_%s_%d.csv" % (request.env.server_name,resource,t2.id)
    243                 return str(db(query).select())
    244             elif representation=="rss":
    245                 #if request.args and request.args[0] in settings.rss_procedures:
    246                 #   feed=eval('%s(*request.args[1:],**dict(request.vars))'%request.args[0])
    247                 #else:
    248                 #   t2._error()
    249                 #import gluon.contrib.rss2 as rss2
    250                 #rss = rss2.RSS2(
    251                 #   title=feed['title'],
    252                 #   link = feed['link'],
    253                 #   description = feed['description'],
    254                 #   lastBuildDate = feed['created_on'],
    255                 #   items = [
    256                 #      rss2.RSSItem(
    257                 #        title = entry['title'],
    258                 #        link = entry['link'],
    259                 #        description = entry['description'],
    260                 #        pubDate = entry['created_on']) for entry in feed['entries']]
    261                 #   )
    262                 #response.headers['Content-Type']='application/rss+xml'
    263                 #return rss2.dumps(rss)
    264                 response.view='plain.html'
    265                 return
    266             else:
    267                 session.error=T("Unsupported format!")
    268                 redirect(URL(r=request))
    269         else:
    270             if method=="create":
    271                 if logged_in:
    272                     if session.s3.audit_write:
    273                         audit_id=db.s3_audit.insert(
    274                             person=auth.user.id,
    275                             operation='create',
    276                             representation=representation,
    277                             module=request.controller,
    278                             resource=resource,
    279                             record=t2.id,
    280                             old_value='',
    281                             new_value=''
    282                         )
    283                     if representation=="html":
    284                         t2.messages.record_created=s3.crud_strings.msg_record_created
    285                         form=t2.create(table)
    286                         # Check for presence of Custom View
    287                         custom_view='%s_create.html' % resource
    288                         _custom_view=os.path.join(request.folder,'views',module,custom_view)
    289                         if os.path.exists(_custom_view):
    290                             response.view=module+'/'+custom_view
    291                         else:
    292                             response.view='create.html'
    293                         title=s3.crud_strings.title_create
    294                         list_btn=A(s3.crud_strings.label_list_button,_href=t2.action(resource),_id='list-btn')
    295                         return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
    296                     elif representation=="plain":
    297                         form=t2.create(table)
    298                         response.view='plain.html'
    299                         return dict(item=form)
    300                     elif representation=="json":
    301                         # ToDo
    302                         # Read in POST
    303                         #file=request.body.read()
    304                         #import_json(table,file)
    305                         item='{"Status":"failed","Error":{"StatusCode":501,"Message":"JSON creates not yet supported!"}}'
    306                         response.view='plain.html'
    307                         return dict(item=item)
    308                     elif representation=="csv":
    309                         # Read in POST
    310                         file=request.vars.filename.file
    311                         try:
    312                             import_csv(table,file)
    313                             reply=T('Data uploaded')
    314                         except:
    315                             reply=T('Unable to parse CSV file!')
    316                         return reply
    317                     else:
    318                         session.error=T("Unsupported format!")
    319                         redirect(URL(r=request))
    320                 else:
    321                     redirect(URL(r=request,c='default',f='user',args='login',vars={'_next':URL(r=request,c=module,f=resource,args='create')}))
    322             elif method=="display":
    323                 redirect(URL(r=request,args=t2.id))
    324             elif method=="update":
    325                 if logged_in:
    326                     if session.s3.audit_write:
    327                         old_value = []
    328                         _old_value=db(db[table].id==t2.id).select()[0]
    329                         for field in _old_value:
    330                             old_value.append(field+':'+str(_old_value[field]))
    331                         audit_id=db.s3_audit.insert(
    332                             person=t2.person_id,
    333                             operation='update',
    334                             representation=representation,
    335                             module=request.controller,
    336                             resource=resource,
    337                             record=t2.id,
    338                             old_value=old_value,
    339                             new_value=''
    340                         )
    341                     if representation=="html":
    342                         t2.messages.record_modified=s3.crud_strings.msg_record_modified
    343                         form=t2.update(table,deletable=False)
    344                         # Check for presence of Custom View
    345                         custom_view='%s_update.html' % resource
    346                         _custom_view=os.path.join(request.folder,'views',module,custom_view)
    347                         if os.path.exists(_custom_view):
    348                             response.view=module+'/'+custom_view
    349                         else:
    350                             response.view='update.html'
    351                         title=s3.crud_strings.title_update
    352                         list_btn=A(s3.crud_strings.label_list_button,_href=t2.action(resource),_id='list-btn')
    353                         return dict(module_name=module_name,modules=modules,options=options,form=form,title=title,list_btn=list_btn)
    354                     elif representation=="plain":
    355                         form=t2.update(table,deletable=False)
    356                         response.view='plain.html'
    357                         return dict(item=form)
    358                     elif representation=="json":
    359                         # ToDo
    360                         item='{"Status":"failed","Error":{"StatusCode":501,"Message":"JSON updates not yet supported!"}}'
    361                         response.view='plain.html'
    362                         return dict(item=item)
    363                     else:
    364                         session.error=T("Unsupported format!")
    365                         redirect(URL(r=request))
    366                 else:
    367                     redirect(URL(r=request,c='default',f='user',args='login',vars={'_next':URL(r=request,c=module,f=resource,args=['update',t2.id])}))
    368             elif method=="delete":
    369                 if logged_in:
    370                     if session.s3.audit_write:
    371                         old_value = []
    372                         _old_value=db(db[table].id==t2.id).select()[0]
    373                         for field in _old_value:
    374                             old_value.append(field+':'+str(_old_value[field]))
    375                         db.s3_audit.insert(
    376                             person=auth.user.id,
    377                             operation='delete',
    378                             representation=representation,
    379                             module=request.controller,
    380                             resource=resource,
    381                             record=t2.id,
    382                             old_value=old_value,
    383                             new_value=''
    384                         )
    385                     t2.messages.record_deleted=s3.crud_strings.msg_record_deleted
    386                     if representation=="ajax":
    387                         t2.delete(table,next='%s?format=ajax' % resource)
    388                     else:
    389                         t2.delete(table,next=resource)
    390                 else:
    391                     redirect(URL(r=request,c='default',f='user',args='login',vars={'_next':URL(r=request,c=module,f=resource,args=['delete',t2.id])}))
    392             elif method=="search":
    393                 if session.s3.audit_read:
    394                     db.s3_audit.insert(
    395                         person=auth.user.id,
    396                         operation='search',
    397                         module=request.controller,
    398                         resource=resource,
    399                         old_value='',
    400                         new_value=''
    401                     )
    402                 if representation=="html":
    403                     if logged_in and deletable:
    404                         db[table].represent=lambda table:shn_list_item(table,resource='%s' % resource,action='display',extra="INPUT(_type='checkbox',_class='delete_row',_name='%s' % resource,_id='%i' % table.id)")
    405                     else:
    406                         db[table].represent=lambda table:shn_list_item(table,resource='%s' % resource,action='display')
    407                     search=t2.search(table)
    408                     # Check for presence of Custom View
    409                     custom_view='%s_search.html' % resource
    410                     _custom_view=os.path.join(request.folder,'views',module,custom_view)
    411                     if os.path.exists(_custom_view):
    412                         response.view=module+'/'+custom_view
    413                     else:
    414                         response.view='search.html'
    415                     title=s3.crud_strings.title_search
    416                     return dict(module_name=module_name,modules=modules,options=options,search=search,title=title)
    417                 else:
    418                     session.error=T("Unsupported format!")
    419                     redirect(URL(r=request))
    420             else:
    421                 session.error=T("Unsupported method!")
    422                 redirect(URL(r=request))
    423 }}}
     32The supporting functions are in {{{models/__db.py}}}:
     33 * http://trac.sahanapy.org/browser/models/__db.py
    42434
    42535== Controller ==