Changes between Initial Version and Version 1 of S3/FieldSelectors


Ignore:
Timestamp:
05/01/14 10:55:13 (8 years ago)
Author:
Dominic König
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • S3/FieldSelectors

    v1 v1  
     1= Field Selectors =
     2
     3Field selectors are a string syntax to specify fields in an S3Resource.
     4
     5== Basic Syntax ==
     6
     7The fundamental syntax of a field selector is:
     8
     9{{{
     10<path><fieldname>
     11}}}
     12
     13The path specifies the table that contains the field.
     14
     15=== Fields in the Master Table ===
     16
     17In the simplest case, the path is just the master table of the resource which is represented by the tilde followed by a period:
     18
     19{{{
     20~.<fieldname>
     21}}}
     22
     23The master table path is mandatory only in URLs but can otherwise be omitted, i.e. the simplest field selector is simply the field name.
     24
     25It is also possible to use the name of the master table without module prefix (e.g. "organisation" for org_organisation) instead of the tilde to refer to the master table.
     26
     27=== Fields in Components ===
     28
     29If the field is in a component resource, then the path is the alias of that component followed by a period:
     30
     31{{{
     32<alias>.<fieldname>
     33}}}
     34
     35By default, the alias is the name of the component table without its module prefix (e.g. "contact" for pr_contact).
     36
     37The alias can also be set explicitly in add_component (e.g. for filtered components).
     38
     39If the alias can not be resolved, an AttributeError will be raised.
     40
     41=== Fields in Referenced Tables ===
     42
     43If the field is in a table that is referenced by a foreign key in the master table, then this can be expressed like:
     44
     45{{{
     46~.<foreign_key>$<fieldname>
     47}}}
     48
     49The $ sign indicates that the field is in the table referenced by this foreign key field.
     50
     51The foreign key field must have a real foreign key constraint, i.e. it must not be a list:reference or an integer pseudo-reference.
     52
     53Similar, if the foreign key is in a component:
     54
     55{{{
     56<alias>.<foreign_key>$<fieldname>
     57}}}
     58
     59=== Fields in Linked Tables ===
     60
     61If the field is in a table that references the master table, but is not a component of it, this can be expressed like:
     62
     63{{{
     64~.<foreign_key>:<linked_table>.<field>
     65}}}
     66
     67In this case, the <foreign_key> is the field in <linked_table> that references the master table (i.e. the so-called "left key").
     68
     69Similar, if the linked table references a component instead of the master table:
     70
     71{{{
     72<alias>.<foreign_key>:<linked_table>.<field>
     73}}}
     74
     75=== Combinations ===
     76
     77It is possible to chain path expressions. Every part of the path is relative to the table specified by any previous parts:
     78
     79{{{
     80~.<foreign_key>$<alias>.<fieldname>
     81}}}
     82
     83...specifies that the field is in a component <alias> of the table referenced by <foreign_key>
     84
     85{{{
     86<alias>.<foreign_key1>$<foreign_key2>$<fieldname>
     87}}}
     88
     89...specifies a field in table that is referenced by <foreign_key2> in a table that is referenced by <foreign_key1> in a component <alias> of the master resource.
     90
     91One should though keep in mind that using multi-table paths requires multi-table joins or multiple sub-queries when filtering data. It should therefore be avoided (e.g. through better modelling) where performance is critical, or generally where it is possible.
     92
     93=== Context Paths ===
     94
     95Context paths allow to use the same filter expression for multiple resources even if they have different relationships to the target field.
     96
     97Consider the following case:
     98
     99For project_project, the location reference is in a component project_location:
     100{{{
     101location.location_id$name
     102}}}
     103
     104For org_office, the location reference is in the master table:
     105{{{
     106~.location_id$name
     107}}}
     108
     109Obviously, the field specified by both selectors is the same - just the path to the field is specific for each resource. Due to these different paths, though, filter queries with either selector can not be re-used for the other resource:
     110
     111{{{#!python
     112# Filter query specific for project_project
     113query = S3FieldSelector("location.location_id$name") == "Example"
     114
     115# Filter query specific for org_office
     116query = S3FieldSelector("~.location_id$name") == "Example"
     117}}}
     118
     119To overcome this, we can configure the resource-specific part of the path as "context" path, using s3db.configure:
     120
     121{{{#!python
     122# Configure the "location" context for project_project:
     123s3db.configure("project_project",
     124               context={"location": "location.location_id"},
     125               )
     126
     127# Configure the "location" context for org_office:
     128s3db.configure("org_office",
     129               context={"location": "~.location_id"},
     130               )
     131}}}
     132
     133Now we can use this "location" context to replace the resource-specific part of the path:
     134{{{
     135(location)$name
     136}}}
     137
     138Through this, we can re-use the filter query for both resources:
     139{{{#!python
     140# Filter expression valid for both project_project and org_office:
     141query = S3FieldSelector("(location)$name") == "Example
     142}}}
     143
     144Only when the field selector gets resolved against each resource (e.g. during add_filter), the "(location)" part is translated according to the respective "context" configuration.
     145