Changes between Version 8 and Version 9 of S3/S3Resource


Ignore:
Timestamp:
10/24/10 07:44:21 (14 years ago)
Author:
Dominic König
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • S3/S3Resource

    v8 v9  
    4444[[Image(s3rest.png)]]
    4545
    46 ==== Passing information between main Controller & Prep ====
    47 Scope normally means that these 2 sections can only talk to each other via globals or the Request object.
    48 
    49 If you need to pass data between them, you can use this trick:
    50 {{{
    51 vars = {} # the surrounding dict
    52 def prep(r, vars):
    53     vars.update(x=y) # the actual variable to pass is x
    54     return True
    55 
    56 response.s3.prep = lambda r, vars=vars: prep(r, vars)
    57 
    58 output = shn_rest_controller(module, resource)
    59 
    60 x = vars.get(x, None)
    61 }}}
    62 
    63 An example usage is in {{{controllers/gis.py}}} for location()
    64 
    65 == Export behavior ==
    66 
    67 The XML export function supports HTTP/GET. If no record ID is specified in the request, this will get a ''list'' attempt, otherwise a ''read'' attempt to the specified record. This is the same as for the Joined Resource Controller in general, except the following behaviour:
    68 
    69   - when attempting to read a joined resource, you will get both the primary record and all belonging records in '''this''' joined resource.
    70   - when attempting to read a primary resource, you will get both the primary record and all belonging records in '''all''' joined resources.
    71 
    72 == Import behavior ==
    73 
    74 The XML import function supports HTTP/PUT, HTTP/POST as well as HTTP/GET with explicit ''create'' and ''update''.
    75 
    76 ''However, the use of POST is actually wrong here and is therefore handled like GET. The only way for list+create with ExtJS, though.''
    77 
    78 The behaviour is similar to the XML Export function:
    79 
    80   - when there is no join in the request, resources will be joined automatically:
    81      - the resource-element of the primary will be imported
    82      - when joined resources for that element are also found in the XML source, they will be imported as well (all)
    83   - when a joined resource is specified in the request, only elements for that joined resource will be imported - no other joined resources and not the primary record either
    84 
    85 The import function can read from the request body (by default), but also pull from files or URL's:
    86 
    87   - to import XML data from files, append a ?filename=<full_path_to_xml_file> variable to the request URL.
    88   - to fetch XML data from URL's, append a ?fetchurl=<fully_qualified_url> variable to the request URL. Sources can be HTTP as well as FTP sources, as long as they export XML data.
    89 
    90 This allows you to transfer resources directly from one Sahana Eden server to the other, e.g.:
    91 
    92 {{{
    93 http://localhost:8000/eden/pr/person/create?format=xml&fetchurl=http://vita.sahanafoundation.org/eden/pr/person.xml
    94 }}}
    95 
    96 fetches all person data (including all joined resources) from vita.sahanafoundation.org and creates or updates corresponding records on localhost.
    97 
    98 === Validation ===
    99 
    100 Imported data is validated using the ''requires'' validators as specified in the models, before comitting them to the database.
    101 
    102 In case of any validation error, no data import will happen at all. Instead, the import data tree with error attributes added to the erroneous elements (see JSON reponse format) will be returned.
    103 
    104 To override this, you may specify "ignore_errors=True" in the URL. In this case the import just skips the erroneous records and always returns a success message (error messages are stored, but not returned). Note that "ignore_errors" is not recommended to be represented in regular a user interface, but just used manually if at all necessary (e.g. in manual pre-population of data).
    105 
    106 '''Note:''' In contrast to validation errors, !IntegrityError and IOError exceptions during data import do not prevent or roll back any data import that happened before the exception, and the returned element tree does not contain any error attributes, and these exceptions can not be overridden by "ignore_errors" either.
    107 
    108 === Onvalidation/Onaccept Callbacks ===
    109 
    110 Import of records happens almost as if they were entered in HTML forms, i.e. ''onvalidation''- and ''onaccept'' callbacks are executed as usual. They receive a pseudo-form as parameter, which is ''Storage()'' instead of ''Form()''. Other than ''Form()'' objects, the pseudo-forms contain only '''form.vars''' (as usual, so most of the callbacks should work without change) and a '''form.method''' (which contains either "create" or "update") to indicate the action (which, in case of XML imports, can '''not''' be determined from the request).
    111 
    112 NOTE: Never redirect from onvalidation or onaccept functions - this would break the XML import! Instead, set a flag in response.s3, and let the calling controller redirect upon this flag.
    113 === Authentication/Auditing ===
    114 
    115 XML imports/exports are fully ''Auth''-enabled, i.e. all actions are checked for permission and support auditing as specified in the Settings.
    116 
    117 === Response Format ===
    118 
    119 The response object to ''create'', ''update'' or ''delete'' requests in both XML as well as JSON representations always contains a JSON body like:
    120 
    121 {{{
    122 {
    123     "status": "success",                 // "success" or "failed"
    124     "statuscode": "200",                 // HTTP Status Code
    125     "message" : "Ok",                    // Message as clear text (optional)
    126     "tree" : {                           // Tree object in the JSON response indicates an error
    127                                          // object containing the originally submitted data tree as described above
    128         "$_my_resource": {
    129 
    130             "myfield": {
    131                 "@value": "xxxx",
    132                 "$": "Bullshit",
    133                 "@error": "Validation Error: myfield must be integer!"    // @error indicates an error for this field
    134             }
    135         }
    136     }
    137 }
    138 }}}
    139 
    140   * ''tree'' is only returned in case of an error during Create or Update actions
    141   * ''@error'' attributes can be re-sent (will be removed by the controller)
    142 
    143 === UUID Mapping and Matching ===
    144 
    145 On data export, all references are mapped from internal id's to uuid's - given that uuid's are present in the referenced table, otherwise the reference field is not represented in XML or JSON at all.
    146 
    147 On data import, all references are mapped back from uuid's to internal id's, provided that the referenced record (with that uuid) exists in the database, otherwise the reference field is not imported (get's a default value).
    148 
    149 On data import with create method, records with matching UUID's will automatically get updated instead of newly created.
    150 
    151 Therefore, for resources that have to be exchanged, the use of UUID's is highly recommended.
    152 
    153 === In-line transformation with XSLT ===
    154 
    155 [[Image(s3xml.png)]]
    156 
    157 The XML/JSON interface uses XSLT to transform data from/to the raw XML/JSON format into foreign formats.
    158 
    159 {{{
    160 <?xml version="1.0"?>
    161 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    162     <xsl:output method="xml"/>
    163     <xsl:template match="/">
    164         <xsl:copy-of select="."/>
    165     </xsl:template>
    166 </xsl:stylesheet>
    167 }}}
    168 
    169 This is just an example template for import/export, but it is not used. Instead, when you specify the native formats "xml" or "json", the raw formats described above are used.
    170 
    171 To enable other formats, you have to:
    172 
    173 For import:
    174 
    175   - put an XSLT template for import into static/xsl/import and name the template <format>.xslt (e.g. pfif.xslt)
    176   - in the file models/01_crud.py add the <format> name to this line:
    177 {{{
    178 shn_xml_import_formats = ["xml", "pfif"]
    179 }}}
    180 
    181 For export analogous:
    182 
    183   - put an XSLT template for export into static/xsl/export and name the template <format>.xslt (e.g. pfif.xslt)
    184   - in the file models/01_crud.py add the <format> name to this line:
    185 {{{
    186 shn_xml_export_formats = ["xml", "pfif"]
    187 }}}
    188 
    189 From there, you can use that format name as either extension or ?format= option in requests:
    190 
    191 Export:
    192 {{{
    193 http://localhost:8000/eden/pr/person/1.pfif
    194 }}}
    195 
    196 Import:
    197 {{{
    198 http://localhost:8000/eden/pr/person/1.pfif/create
    199 }}}
    200 
    201 and the corresponding XSL template will now be used at import/export from/into that format.
    202 
    203 Note: "json" and "xml" '''must''' be in the format lists in models/01_crud.py!
    204 
    205  * [http://free.editix.com/features/xslt_debugger.html EditiX] - free GUI XSLT debugger (Java-based, so x-platform)
    206  * [http://xalan.apache.org Xalan] - free CLI XSLT debugger (Java-based, so x-platform)
    207  * Docs: [wiki:DeveloperGuidelinesTips#XSLT]
    208 
    20946----
    21047DeveloperGuidelines