Changes between Version 87 and Version 88 of S3/S3REST/s3_rest_controller


Ignore:
Timestamp:
06/13/14 12:15:51 (7 years ago)
Author:
MattS
Comment:

syntax highlighting

Legend:

Unmodified
Added
Removed
Modified
  • S3/S3REST/s3_rest_controller

    v87 v88  
    1414Using {{{s3_rest_controller}}}, a basic RESTful controller for the {{{pr_image}}} table can look like:
    1515
    16 {{{
     16{{{#!python
    1717def image():
    1818
     
    3030== Basic Syntax ==
    3131
    32 {{{
     32{{{#!python
    3333output = s3_rest_controller(prefix, resourcename)
    3434}}}
     
    4444All of the following options are set using:
    4545
    46 {{{
     46{{{#!python
    4747s3mgr.configure(table, key=value)
    4848}}}
     
    5454
    5555You can specify multiple settings at once:
    56 {{{
     56{{{#!python
    5757s3mgr.configure(table, key1=value1, key2=value2, ...)
    5858}}}
     
    6262You can also delete a particular setting by:
    6363
    64 {{{
     64{{{#!python
    6565s3mgr.model.clear_config(table, "key")
    6666}}}
     
    7272You can define which of the CRUD functions are allowed for your resource. By default, they all are True.
    7373
    74 {{{
     74{{{#!python
    7575  s3mgr.configure(table, editable=True,             # Records can be updated
    7676                         insertable=True,           # New records can be added
     
    9292This setting takes a list of field names of the fields to be displayed:
    9393
    94 {{{
     94{{{#!python
    9595s3mgr.configure(table,
    9696                list_fields=["id", "name", "location_id"])
     
    101101For virtual fields, you should provide a tuple of {{{(T("FieldLabel"), "fieldname")}}}, because virtual fields do not have a {{{.label}}} setting (as they are functions and not {{{Field}}} instances):
    102102
    103 {{{
     103{{{#!python
    104104s3mgr.configure(table,
    105105                list_fields=["id",
     
    113113To include a field from a referenced table, insert the field name as "<foreign_key>$<fieldname>", e.g.:
    114114
    115 {{{
     115{{{#!python
    116116s3mgr.configure(table,
    117117                list_fields=["id",
     
    134134The redirection destination can be configured per DB table, using:
    135135
    136 {{{
     136{{{#!python
    137137s3mgr.configure(table, create_next=url)
    138138}}}
    139 {{{
     139{{{#!python
    140140s3mgr.configure(table, update_next=url)
    141141}}}
    142 {{{
     142{{{#!python
    143143s3mgr.configure(table, delete_next=url)
    144144}}}
     
    168168You can define extra form validation methods to be invoked after a create/update form has successfully passed the indivdual field validation, by using:
    169169
    170 {{{
     170{{{#!python
    171171s3db.configure(tablename, create_onvalidation=callback)
    172172}}}
    173 {{{
     173{{{#!python
    174174s3db.configure(tablename, update_onvalidation=callback)
    175175}}}
     
    182182If either of {{{create_onvalidation}}} or {{{update_onvalidation}}} is not set, then the {{{onvalidation}}} setting is tried:
    183183
    184 {{{
     184{{{#!python
    185185s3db.configure(tablename, onvalidation=callback)
    186186}}}
     
    191191
    192192Any validation errors are to be reported directly into the form as:
    193 {{{
     193{{{#!python
    194194form.errors[fieldname] = error_msg
    195195}}}
     
    208208You can define methods to be invoked after a record has been created/updated, by using:
    209209
    210 {{{
     210{{{#!python
    211211s3db.configure(tablename, create_onaccept=callback)
    212212}}}
    213 {{{
     213{{{#!python
    214214s3db.configure(tablename, update_onaccept=callback)
    215215}}}
     
    222222If either of {{{create_onaccept}}} or {{{update_onaccept}}} is not set, then the {{{onaccept}}} setting is tried:
    223223
    224 {{{
     224{{{#!python
    225225s3db.configure(tablename, onaccept=callback)
    226226}}}
     
    234234You can specify callbacks to be invoked when a record is to be deleted:
    235235
    236 {{{
     236{{{#!python
    237237s3db.configure(tablename, ondelete_cascade=callback)
    238238}}}
     
    251251You can also define callbacks to be invoked ''after'' a record has been deleted:
    252252
    253 {{{
     253{{{#!python
    254254s3db.configure(tablename, ondelete=callback)
    255255}}}
     
    277277However, some tables may by their nature only contain one or few rows, and then server-side pagination is not needed (in fact, inefficient). In these cases, the respective controller can turn it off by:
    278278
    279 {{{
     279{{{#!python
    280280response.s3.no_sspag=True
    281281}}}
     
    321321To choose a custom view, you can easily override the default setting ''after'' s3_rest_controller returns:
    322322
    323 {{{
     323{{{#!python
    324324  output = s3_rest_controller(prefix, resourcename)
    325325
     
    332332In interactive view formats, any additional named arguments in the {{{s3_rest_controller}}} argument list will be added to the view variables:
    333333
    334 {{{
     334{{{#!python
    335335output = s3_rest_controller(prefix, resourcename, **attr)
    336336}}}
     
    345345A typical use-case is '''rheader''':
    346346
    347 {{{
     347{{{#!python
    348348def my_rheader(r):
    349349  if r.interactive and r.component:
     
    356356}}}
    357357
    358 If {{{my_rheader(r)}}} gives something else than {{{None}}}, then this value is added as {{{rheader}}} to the view variables.
     358If {{{my_rheader(r)}}} gives something else than {{{#!python None}}}, then this value is added as {{{rheader}}} to the view variables.
    359359
    360360== Advanced Options ==
     
    363363
    364364You can filter lists in the controller by setting {{{response.s3.filter}}} to a filter query:
    365 {{{
     365{{{#!python
    366366    # This filters for females:
    367367    response.s3.filter = (db.pr_person.gender == 2)
     
    375375
    376376In {{{prep}}}, you can also add filter queries using the {{{add_filter}}} method:
    377 {{{
     377{{{#!python
    378378    def prep(r):
    379379        resource = r.resource
     
    393393
    394394To have the primary resource unfiltered, and filter only records in a particular component, you can use {{{add_component_filter}}}:
    395 {{{
     395{{{#!python
    396396    def prep(r):
    397397        resource = r.resource
     
    423423To '''pre-populate''' Create-forms '''from the controller''', you can specify the variable {{{populate}}} in the arguments of {{{s3_rest_controller}}}:
    424424
    425 {{{
     425{{{#!python
    426426output = s3_rest_controller(prefix, resourcename,
    427427                            populate=dict(fieldname1=value1,
     
    432432Instead of a {{{dict}}}, you can also pass a callable object as {{{populate}}}. This will be executed with the current {{{S3Request}}} and the named arguments of {{{s3_rest_controller}}} in order to produce the field/value {{{dict}}}:
    433433
    434 {{{
     434{{{#!python
    435435def populate(r, **attr):
    436436    """
     
    454454Note that {{{populate}}} will only be applied in {{{GET}}} requests and only if no record_id is specified. That means, if it uses a separate form to generate the data, you need to revert the request into {{{GET}}} in order to have the create-form pre-populated:
    455455
    456 {{{
     456{{{#!python
    457457data = None
    458458form = FORM(...some form...)
     
    480480A prep hook would allow you to change a handler configuration in certain situations, e.g. testing a URL variable:
    481481
    482 {{{
     482{{{#!python
    483483def myresource():
    484484
     
    511511
    512512If you need to pass data between them, you can use this trick:
    513 {{{
     513{{{#!python
    514514vars = {} # the surrounding dict
    515515def prep(r, vars):
     
    531531The s3_rest_controller has multiple hooks,Look at how s3_rest_controller is actually defined in models/00_utils.py:
    532532
    533 {{{
     533{{{#!python
    534534def s3_rest_controller(prefix=None, resourcename=None, **attr):
    535535
     
    581581This could be your "warehouse" CRUD controller:
    582582
    583 {{{
     583{{{#!python
    584584def warehouse():
    585585
     
    591591At first you implement your report function (in the controller file). This function takes the argument r (=S3Request) and a dict of named arguments (just the same named arguments from the s3_rest_controller call above). This function returns the report. Then, in your controller, you plug in this function to your resource - together it would look like that:
    592592
    593 {{{
     593{{{#!python
    594594def warehouse():
    595595
     
    617617found in r:
    618618
    619 {{{
     619{{{#!python
    620620def warehouse_report(r, **attr):
    621621
     
    647647To produce the XML report, it is probably sufficient to just export the requested warehouse information in S3-XML, and then use XSLT stylesheets to produce the finally desired XML formats. That's pretty easy:
    648648
    649 {{{
     649{{{#!python
    650650def warehouse_report(r, **attr):
    651651    ...
     
    657657Perhaps you want to add an RSS feed:
    658658
    659 {{{
     659{{{#!python
    660660def warehouse_report(r, **attr):
    661661    ...
     
    682682
    683683In case a specific record has been requested, you can access it as:
    684 {{{
     684{{{#!python
    685685    record = r.record
    686686}}}
    687687If r.record is None, then the request is targeting all warehouse records, so you'd take:
    688 {{{
     688{{{#!python
    689689    table = r.table
    690690    records = db().select(table.ALL)