Changes between Version 79 and Version 80 of S3/S3REST/s3_rest_controller


Ignore:
Timestamp:
06/04/13 21:07:53 (12 years ago)
Author:
hardik juneja
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • S3/S3REST/s3_rest_controller

    v79 v80  
    505505=== Custom Methods ===
    506506
     507If you have a resource "warehouse" and want to implement a function "report" that generates a report about the current status of the warehouse.
     508
     509Now you're gonna provide this report in a RESTful way, i.e. you want to provide it as a resource that can be addressed via URLs like:
     510
     511  - '''!http://site.myserver.org/eden/wm/warehouse/report'''
     512
     513and is provided in several different data formats beyond HTML (the interactive view), let's say - XLS and XML:
     514
     515  - '''!http://site.myserver.org/eden/wm/warehouse/report.xls'''
     516  - '''!http://site.myserver.org/eden/wm/warehouse/report.xml'''
     517
     518you can use s3_rest_controller for this!
     519
     520This could be your "warehouse" CRUD controller:
     521
     522{{{
     523def warehouse():
     524
     525   """ RESTful CRUD controller """
     526
     527   return s3_rest_controller(module, resource, ...)
     528}}}
     529
     530At first you implement your report function (in the controller file). This function takes the argument r (=S3RESTRequest) 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:
     531
     532{{{
     533def warehouse():
     534
     535    """ RESTful CRUD+Reports controller """
     536
     537    # Plug warehouse_report into warehouse resource:
     538    s3db.set_method(module, resource, method="report", action=warehouse_report)
     539
     540    return shn_rest_controller(module, resource, ...)
     541
     542def warehouse_report(r, **attr):
     543
     544    """ Warehouse report generator """
     545
     546    # Code to produce the report goes here
     547    report = ...
     548
     549    return report
     550}}}
     551
     552Note that if "report" is a dict, then the REST controller automatically adds the S3Request as "r" to that dict before returning it. Thus, "r" is
     553available to the view templates. That also means: do not use "r" as key in that dict.
     554
     555However, there may be other formats than HTML - to implement other formats, you might need to check for the representation of the request. This can be
     556found in r:
     557
     558{{{
     559def warehouse_report(r, **attr):
     560
     561    """ Warehouse report generator """
     562
     563    if r.representation in ("html", "popup"):
     564        # Code to produce the report items:
     565        title = T("Warehouse Report")
     566
     567        # Assemble the report items in a dict:
     568        report = dict(title=title, ...)
     569
     570    elif r.representation == "xls":
     571        # Code to produce the XLS report goes here
     572        ...
     573
     574    elif r.representation in s3_xml_export_formats:
     575        # Code to produce the XML report goes here
     576        ...
     577
     578    else:
     579        r.error(501, r.ERROR.BAD_FORMAT)
     580
     581    return report
     582}}}
     583
     584See [wiki:S3XRC#RESTfulAPI#S3Request S3Request] to find out more about "r".
     585
     586To 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:
     587
     588{{{
     589def warehouse_report(r, **attr):
     590    ...
     591    elif r.representation in s3_xml_export_formats:
     592        report = export_xml(xrequest)
     593    ...
     594}}}
     595
     596Perhaps you want to add an RSS feed:
     597
     598{{{
     599def warehouse_report(r, **attr):
     600    ...
     601    elif r.representation == "rss":
     602        # Code to produce the RSS report goes here
     603        report = ...
     604    ...
     605}}}
     606
     607Getting the data from the warehouse_report.
     608
     609Your implementation already supports a variety of URLs:
     610
     611This URL addresses the report for all warehouses:
     612  - '''!http://site.myserver.org/eden/wm/warehouse/report'''
     613
     614This URL addresses the report for the warehouse record with ID=1.
     615  - '''!http://site.myserver.org/eden/wm/warehouse/1/report'''
     616
     617This URL addresses the report in XLS format for the warehouse record with the UUID=123654278 (assuming that you have UUID's in your warehouse table).
     618  - '''!http://site.myserver.org/eden/wm/warehouse/report.xls?warehouse.uid=123654278'''
     619
     620The S3Request provides the resource information to your warehouse_report function.
     621
     622In case a specific record has been requested, you can access it as:
     623{{{
     624    record = r.record
     625}}}
     626If r.record is None, then the request is targeting all warehouse records, so you'd take:
     627{{{
     628    table = r.table
     629    records = db().select(table.ALL)
     630    for record in records:
     631       ...
     632}}}
     633instead.
     634
     635NOTE: representation in r is always all lowercase, there is no differentiation between the ".XML" and ".xml" extension in the URL.
     636
     637And...not to forget: your warehouse_report is still a controller function, that means you can implement forms as usual (e.g. operated with form.accepts or web2py Crud).
     638
     639
    507640----
    508641