= S3 RESTful API - URL Format = [[TOC]] - see also: [wiki:S3/S3REST/Methods Standard Methods] == URL Format == - ''Parts in { } mark optional parts, [ A | B ] indicates alternatives'' === Basic URL Format === The basic URL format is: !http:// '''server''' / '''application''' / '''prefix''' / '''name'''{ /<'''arguments'''> }{ ?<'''query'''> } ''Example:'' {{{ http://demo.eden.sahanafoundation.org/eden/org/office/4/human_resource?~.person_id$first_name__like=Nor* }}} ||=''Part''=||=''Explanation''=||=''Example''=|| ||'''Server'''||the server URL||{{{demo.eden.sahanafoundation.org}}}|| ||'''Application'''||the web2py application name||{{{eden}}}|| ||'''Prefix'''||the module prefix||{{{org}}}|| ||'''Name'''||the resource name||{{{office}}}|| ||'''Arguments'''||''see arguments list format''||{{{4/human_resource}}}|| ||'''Query'''||''see query format''||{{{~.person_id$first_name__like=Nor*}}}|| === Arguments List Format === The arguments list consists of: { /'''id''' }{ / [ '''method''' | '''component''' { /'''component_id''' } { /'''method''' } ] } ''Example:'' {{{ 4/human_resource }}} ||=''Part''=||=''Explanation''=||=''Example''=|| ||'''ID'''||the master record ID||{{{4}}}|| ||'''Method'''||the resource method (e.g. /create or /summary)||''not present in example''|| ||'''Component'''||the component resource (projected table)||{{{human_resource}}}|| ||'''Component ID'''||the component record ID||''not present in example''|| === Query Format === The basic query format is: '''field-selector'''{'''operator'''}='''value(s)''' ''Example:'' {{{ ~.person_id$first_name__like=Nor* }}} ||=''Part''=||=''Explanation''=||=''Example''=|| ||'''Field Selector'''||the field selector||{{{~.person_id$first_name}}}|| ||'''Operator'''||the query operator||{{{__like}}}|| ||'''Value(s)'''||the search values||{{{Nor*}}}|| * {{{NONE}}} as value is interpreted as a NULL-value (=Python {{{None}}}) * multiple values can be specified separated by commas * a value enclosed in double quotes {{{"}}} is treated as string constant - i.e. commas and {{{NONE}}} inside the string will not be interpreted * only the {{{__like}}} operator interprets the asterisk {{{*}}} as wildcard (all other operators do not!) ==== Field Selectors ==== See also: [wiki:S3/FieldSelectors] The general field selector syntax is: '''alias'''.{'''left-key''':'''link-table'''.}{'''foreign-key'''$}['''field-selector''' | '''field-name'''] ''Example:'' {{{ ~.person_id$first_name }}} ||=''Part''=||=''Explanation''=||=''Example''=|| ||'''Alias'''||is the alias of the component without prefix (note that components may use aliases different from their table name). ||{{{~}}}|| ||'''Left Key'''||the foreign key field in a backward-reference (=link table points back to master/component), can be omitted if not ambiguous|| || ||'''Link Table'''||the table name of the backward-referencing table (incl. prefix)|| || ||'''Foreign Key'''||foreign key field in a forward-reference (=component points to a referenced table), ||{{{person_id}}}|| ||'''Field Name'''||the target field name||{{{first_name}}}|| * For the master table of of the request, the '''alias''' is the tablename without prefix or just {{{~}}} * Foreign key references can be chained (separated by $) if the referenced table is more than one reference level away, like in {{{resource.foreign_key$foreign_key$fieldname=value}}} * "integer", "list:reference" or virtual fields are not real foreign keys and can therefore not be used for $-joins * Field selectors represent the ''path'' to the target field (interpreted left-to-right), starting with the master resource or a component of it * Queries with invalid or unresolvable field selectors are ignored (but logged on stderr if in debug mode) ==== Query Operators ==== ||=''Operator''=||=''Method''=||=''Comments''=|| ||!__eq||equal, ==||can be omitted|| ||!__ne||not equal, !=|| || ||!__lt||less than, <||numeric and date types only|| ||!__le||less than or equal, <=||numeric and date types only|| ||!__gt||greater than, >||numeric and date types only|| ||!__ge||greater than or equal, >=||numeric and date types only|| ||!__like||wildcard matching, use * as wildcard||string/text types only|| ||!__contains||(full) containment||list types only|| ||!__anyof||(partial) containment||list types only|| ||!__belongs||reverse containment|||| ||!__typeof||[wiki:S3/S3Hierarchy#HierarchicalQueryOperatortypeof hierarchical type recognition]|||| * to negate a query, append {{{!}}} to the operator, e.g. {{{resource.fieldname__like!=value}}} * the {{{__like}}} operator works case-insensitive, whereas {{{__contains}}} is case-sensitive. ==== Examples ==== Find persons whose first name starts with "Mir": {{{ /pr/person?person.first_name__like=Mir* }}} The tilde {{{~}}} refers to the master resource addressed by the URL, i.e. this one is equivalent to the former: {{{ /pr/person?~.first_name__like=Mir* }}} Find offices with location names which start with "Osl": {{{ /org/office?~.location_id$name__like=Osl* }}} Query operators can be negated by inserting a {{{!}}}, i.e. find offices with location names which do ''not'' start with "Osl": {{{ /org/office?~.location_id$name__like!=Osl* }}} Find all people *without* a specific [set of] qualification(s): This isn't supported out of the box, as it cannot be done with WHERE clause(s). However it is easy to do it with a little custom code: {{{ def customise_pr_person_resource(r, tablename): # Filtered Component to allow an exclusive filter s3db = current.s3db ctable = s3db.hrm_certificate query = (ctable.name.like("Fire%")) & \ (ctable.deleted == False) rows = current.db(query).select(stable.id) fire_cert_ids = [row.id for row in rows] s3db.add_components("pr_person", hrm_certification = {"name": "missing_qualification", "joinby": "person_id", "filterby": {"certificate_id": fire_cert_ids}, }, ) settings.customise_pr_person_resource = customise_pr_person_resource }}} Then you can do: {{{ /pr/person?missing_qualification.id=None }}} (This can be then further refined using standard UI Filter Widgets) == Bracketed OR Queries == If there is a need for a more complex query, such as one which requires a bracketed OR filter, then you can use the new {{{$filter}}} syntax,e.g.: {{{ ?$filter=(start_date lt "2012-01-01") and ((end_date gt "2012-10-01") or (end_date eq None)) }}} NB Be sure to quote string literals, including dates == Boundary Box Queries == For resources with location references (e.g. Hospitals), you can use boundary box queries select records. The general format of the query variable is: - ?bbox=minLon,minLat,maxLon,maxLat You can also specify the foreign key field name of the location reference the query relates to (e.g. in case there are multiple location references in that resource): - ?bbox.FKFieldName=minLon,minLat,maxLon,maxLat Examples: {{{ /hms/hospital?bbox=123,13.5,124,13.7 }}} {{{ /hms/hospital?bbox.location_id=123,13.5,124,13.7 }}} == Bypassing !FilterForm Default Filters == 'Hard' Filters (added by the developers in the controller) can never be bypassed by URL filters. However 'Soft' Filters which are where a !FilterForm is configured to have [wiki:S3/FilterForms#Configuration Default Filters] for convenience of interactive users rather than security, or other meaning, can be. To instruct a !FilterForm to NOT implement the Default Filters, add {{{?default_filters=0}}} to the URL. * Note that these aren't required for non-interactive requests, such as XML, GeoJSON, XLS, etc == URL Examples == ==== Interactive (HTML) Format ==== * http://127.0.0.1:8000/eden/pr/person ==== Non-interactive Formats ==== * http://127.0.0.1:8000/eden/pr/person.pdf * http://127.0.0.1:8000/eden/pr/person.rss * http://127.0.0.1:8000/eden/pr/person.xml ==== URL Method (GET) ==== * http://127.0.0.1:8000/eden/pr/person/create ==== Record by ID ==== * http://127.0.0.1:8000/eden/pr/person/1 * http://127.0.0.1:8000/eden/pr/person/1.pfif * http://127.0.0.1:8000/eden/pr/person/1.json ==== Record by UID ==== * http://127.0.0.1:8000/eden/pr/person?person.uid=37988e29-4e7c-4f71-bb32-93ce1a2ba1ac ==== URL Queries ==== * http://127.0.0.1:8000/eden/pr/person?person.id=1,2,3 * http://127.0.0.1:8000/eden/org/office?office.type=None,1,2,3,4&office.obsolete=False * http://127.0.0.1:8000/eden/org/office?office.modified_on__gt=YYYYMMDDTHH:mm:ss - ''(can use current.xml.ISOFORMAT as format string)'' * [[http://127.0.0.1:8000/eden/pr/person.pfif?person.first_name__like=Dominic*]] * http://127.0.0.1:8000/eden/pr/person.xml?contact.value__like=*gmail.com ---- DeveloperGuidelines