doc/book/en/development/devweb/facets.rst
branchstable
changeset 4751 1a9d2c3c7f0c
parent 4446 a413fac5ff5e
child 5286 43d7044f8d0b
equal deleted inserted replaced
4750:875dc33551a9 4751:1a9d2c3c7f0c
    21                                     composite='subject')
    21                                     composite='subject')
    22 
    22 
    23 The two other entity types defined in the schema are `Visit` and `Agency` but we
    23 The two other entity types defined in the schema are `Visit` and `Agency` but we
    24 can also guess from the above that this application uses the two cubes
    24 can also guess from the above that this application uses the two cubes
    25 `comment`_ and
    25 `comment`_ and
    26 `addressbook`_ (remember, cubicweb is only a game where you assemble cubes !). 
    26 `addressbook`_ (remember, cubicweb is only a game where you assemble cubes !).
    27 
    27 
    28 While we know that just defining the schema in enough to have a full, usable,
    28 While we know that just defining the schema in enough to have a full, usable,
    29 (testable !) application, we also know that every application needs to be 
    29 (testable !) application, we also know that every application needs to be
    30 customized to fulfill the needs it was built for. So in this case, what we
    30 customized to fulfill the needs it was built for. So in this case, what we
    31 needed most was some custom filters that would let us restrict searches
    31 needed most was some custom filters that would let us restrict searches
    32 according
    32 according
    33 to surfaces, prices or zipcodes. Fortunately for us, Cubicweb provides the
    33 to surfaces, prices or zipcodes. Fortunately for us, Cubicweb provides the
    34 **facets** (image_) mechanism and a few base classes that make the task quite
    34 **facets** (image_) mechanism and a few base classes that make the task quite
    35 easy:
    35 easy:
    36 
    36 
    37 .. sourcecode:: python
    37 .. sourcecode:: python
    38 
    38 
    39   class PostalCodeFacet(RelationFacet): 
    39   class PostalCodeFacet(RelationFacet):
    40       id = 'postalcode-facet'             # every registered class must have an id
    40       __regid__ = 'postalcode-facet'             # every registered class must have an id
    41       __select__ = implements('Office')   # this facet should only be selected when 
    41       __select__ = implements('Office')   # this facet should only be selected when
    42                                           # visualizing offices
    42                                           # visualizing offices
    43       rtype = 'has_address'               # this facet is a filter on the entity linked to
    43       rtype = 'has_address'               # this facet is a filter on the entity linked to
    44                                           # the office thrhough the relation
    44                                           # the office thrhough the relation
    45                                           # has_address
    45                                           # has_address
    46       target_attr = 'postalcode'          # the filter's key is the attribute "postal_code"
    46       target_attr = 'postalcode'          # the filter's key is the attribute "postal_code"
    55 `Office`:
    55 `Office`:
    56 
    56 
    57 .. sourcecode:: python
    57 .. sourcecode:: python
    58 
    58 
    59   class SurfaceFacet(AttributeFacet):
    59   class SurfaceFacet(AttributeFacet):
    60       id = 'surface-facet'              # every registered class must have an id
    60       __regid__ = 'surface-facet'              # every registered class must have an id
    61       __select__ = implements('Office') # this facet should only be selected when 
    61       __select__ = implements('Office') # this facet should only be selected when
    62                                         # visualizing offices
    62                                         # visualizing offices
    63       rtype = 'surface'                 # the filter's key is the attribute "surface" 
    63       rtype = 'surface'                 # the filter's key is the attribute "surface"
    64       comparator = '>='                 # override the default value of operator since 
    64       comparator = '>='                 # override the default value of operator since
    65                                         # we want to filter according to a
    65                                         # we want to filter according to a
    66                                         # minimal 
    66                                         # minimal
    67                                         # value, not an exact one
    67                                         # value, not an exact one
    68 
    68 
    69       def rset_vocabulary(self, ___):
    69       def rset_vocabulary(self, ___):
    70           """override the default vocabulary method since we want to hard-code
    70           """override the default vocabulary method since we want to hard-code
    71           our threshold values. 
    71           our threshold values.
    72           Not overriding would generate a filter box with all existing surfaces
    72           Not overriding would generate a filter box with all existing surfaces
    73           defined in the database.
    73           defined in the database.
    74           """
    74           """
    75           return [('> 200', '200'), ('> 250', '250'),
    75           return [('> 200', '200'), ('> 250', '250'),
    76                   ('> 275', '275'), ('> 300', '300')]
    76                   ('> 275', '275'), ('> 300', '300')]
    91 define restrictions `filters`_ really as easily as possible.
    91 define restrictions `filters`_ really as easily as possible.
    92 
    92 
    93 We've just added two new kind of facets in CubicWeb :
    93 We've just added two new kind of facets in CubicWeb :
    94 
    94 
    95 - The **RangeFacet** which displays a slider using `jquery`_
    95 - The **RangeFacet** which displays a slider using `jquery`_
    96   to choose a lower bound and an upper bound. The **RangeWidget** 
    96   to choose a lower bound and an upper bound. The **RangeWidget**
    97   works with either numerical values or date values
    97   works with either numerical values or date values
    98 
    98 
    99 - The **HasRelationFacet** which displays a simple checkbox and
    99 - The **HasRelationFacet** which displays a simple checkbox and
   100   lets you refine your selection in order to get only entities
   100   lets you refine your selection in order to get only entities
   101   that actually use this relation.
   101   that actually use this relation.
   102 
   102 
   103 .. image :: http://www.cubicweb.org/Image/343498?vid=download
   103 .. image :: http://www.cubicweb.org/Image/343498?vid=download
   104 
   104 
   105 
   105 
   106 Here's an example of code that defines a facet to filter 
   106 Here's an example of code that defines a facet to filter
   107 musical works according to their composition date:
   107 musical works according to their composition date:
   108 
   108 
   109 .. sourcecode:: python
   109 .. sourcecode:: python
   110 
   110 
   111     class CompositionDateFacet(DateRangeFacet):
   111     class CompositionDateFacet(DateRangeFacet):
   112         # 1. make sure this facet is displayed only on Track selection
   112         # 1. make sure this facet is displayed only on Track selection
   113         __select__ = DateRangeFacet.__select__ & implements('Track')
   113         __select__ = DateRangeFacet.__select__ & implements('Track')
   114         # 2. give the facet an id required by CubicWeb)
   114         # 2. give the facet an id required by CubicWeb)
   115         id = 'compdate-facet'
   115         __regid__ = 'compdate-facet'
   116         # 3. specify the attribute name that actually stores the date in the DB
   116         # 3. specify the attribute name that actually stores the date in the DB
   117         rtype = 'composition_date'
   117         rtype = 'composition_date'
   118 
   118 
   119 And that's it, on each page displaying tracks, you'll be able to filter them
   119 And that's it, on each page displaying tracks, you'll be able to filter them
   120 according to their composition date with a jquery slider.
   120 according to their composition date with a jquery slider.