Luke Plant avatar Luke Plant committed 05402c1

Lots of updates to docs

Comments (0)

Files changed (4)

 Status
 ======
 
-The library is in a useful state, but not quite 'complete'. The main glaring
-feature omission in nice handling of Decimal fields (or other numeric fields that need
-to be treated as a continuum of values) to provide range-base selection.
-
-The internal API of Filter and FilterSet are not firmed up, but are not far from
-being so. Test coverage is extensive.
-
-Feedback regarding API or features is very welcome!
+The library is in a useful state and is used in production. Test coverage is
+extensive. Feedback regarding API or features is very welcome!
 
 TODO
 ====
 
-* Automatic range-based filters for DecimalFields - e.g. for prices
-* Ability to specify 'defaults' attribute for FilterSet
+* Possible: ability to specify 'defaults' attribute for FilterSet
 * Allow the automatic 'page' resetting to be customized
 classes will be chosen depending on the type of field. They are listed below,
 with the keyword argument options that they take.
 
-At the moment, all other methods of Filter and subclasses are considered private
-implementation details, until all the Filters are implemented and the API firms
-up.
-
 .. class:: Filter
 
    This is the base class for all filters, and has provides some options:
      If ``'year'`` or ``'month'`` is specified, the drill-down will be limited
      to that level.
 
+.. class:: NumericRangeFilter
+
+   This filter produces ranges of values for a numeric field. It is the default
+   filter for decimal fields, but can also be used with integer fields. It
+   attempts to make the ranges 'look nice' using rounded numbers in an automatic
+   way. It uses 'drill-down' like DateTimeFilter.
+
+   It takes the following options:
+
+   * ``max_links``
+
+     Default: 5
+
+     The maximum number of links to display. If there fewer distinct values
+     than this in the data, single values will be shown, otherwise ranges.
+
+   * ``ranges``
+
+     Default: None
+
+     If this is specified, it will override the (initial) automatic range. The
+     value should be a list of ranges, where each item in the list is either:
+
+     * a two-tuple containing the beginning and end range values
+
+     * a three-tuple containing the beginning and end range values
+       and a custom label.
+
+   * ``drilldown``
+
+     Default: True
+
+     If ``False``, only one level of choices will be displayed.
+
+   The 'end points' of ranges are handled in the following way: the lower bound
+   is exclusive, and the upper bound is inclusive, apart from for the first
+   range, where both are inclusive. This is designed for a fairly intuitive
+   behaviour.
+
 .. class:: ValuesFilter
 
    This is the fallback that is used when nothing else matches.
+
+.. _custom-filter-classes:
+
+Custom Filter classes
+=====================
+
+As described in the :class:`~django_easyfilters.FilterSet` documentation, you
+can provide your own Filter class for a field. If you do so, it is expected to
+have the following API:
+
+* ``__init__(field, model, params, **kwargs)``
+
+  Constructor. ``field`` is the string identifying the field, ``model`` is the
+  model class, ``params`` is a QueryDict (i.e. request.GET). ``kwargs`` contains
+  any custom options specified for the filter.
+
+* ``apply_filter(qs)``
+
+  This method takes the QuerySet ``qs`` and returns a QuerySet that has filters
+  applied to it, where the filter parameters are defined in the ``params`` that
+  were passed to the constructor. The method must be able to extract the
+  relevant parameter, if it exists, and filter the QuerySet accordingly.
+
+* ``get_choices(qs)``
+
+  This method is passed a fully filtered QuerySet, and must return a list of
+  choices to present to the user. The choices should be instances of
+  ``django_easyfilters.filters.FilterChoice``, which has the attributes:
+
+  * label: User presentable text string for the choice
+  * link_type: choice of FILTER_ADD, FILTER_REMOVE, FILTER_DISPLAY
+  * count: the number of items for this choice (only for FILTER_ADD)
+  * params: parameters used to create a link for this option, as a QueryDict
+
+At the moment, all other methods of Filter and subclasses are considered private
+implementation details. You can subclass Filter if you want, and use its
+functionality, but it may change without warning.
+
+

docs/filterset.rst

           genre = models.ForeignKey(Genre)
           date_published = models.DateField()
 
-   You could create a BookFilterSet like this:
+   ...you could create a BookFilterSet like this:
 
    .. code-block:: python
 
-
        class BookFilterSet(FilterSet):
            fields = [
                'genre',
                'date_published',
            ]
 
-   The items in the fields attribute can also be two-tuples containing first
+   Each item in the fields attribute can also be a two-tuple containing first
    the field name and second a dictionary of options to be passed to the
-   :doc:`filters <filters>` as keyword arguments.
+   :doc:`filters <filters>` as keyword arguments, or a three-tuple containing
+   the field name, a dictionary of options, and a Filter class. In this way you
+   can override default options and the default filter type used e.g.:
 
+   .. code-block:: python
+
+       from django_easyfilters.filters import ValuesFilter
+
+       class BookFilterSet(FilterSet):
+           fields = [
+               ('genre', dict(order_by_count=True)),
+               ('date_published', {}, ValuesFilter),
+           ]
+
+   This also allows :ref:`custom Filter classes <custom-filter-classes>` to be used.
 
    To use the BookFilterSet, please see :doc:`the overview instructions
    <overview>`. The public API of ``FilterSet`` for use consists of:
       This attribute contains the input QuerySet filtered according to the data
       in ``params``.
 
-
-   In addition, there are methods that can be overridden to customise the FilterSet:
-
+   In addition, there are methods/attributes that can be overridden to customise
+   the FilterSet:
 
    .. method:: get_template(field_name)
 
 
         * ``count``: for those that are ``add`` links, the number of items in
           the QuerySet that match that choice.
+
+   .. attribute:: template
+
+      A string containing a Django template, used to render all the filters.  It
+      is used by the default ``get_template`` method, see above.

docs/overview.rst

        {# etc #}
     {% endfor %}
 
-To add the filters, in views.py, you would add a FilterSet subclass and change
-the view code as follow:
+To add the filters, in views.py add a FilterSet subclass and change the view
+code as follow:
 
 .. code-block:: python
 
 applied to it, as defined by BookFilterSet and the information from the query
 string (request.GET).
 
-The ``booksfilter`` item has been added, in order for the filters to be
-displayed on the template.
+The ``booksfilter`` item has been added to the context in order for the filters
+to be displayed on the template.
 
 Then, in the template, just add ``{{ booksfilter }}`` to the template.
 books. You can also use pagination e.g. using django-pagination:
        {# etc #}
     {% endfor %}
 
-Customisation of the filters can be done using a tuple containing (``field_name``,
-dict of options), instead of just ``field_name``::
-
-    class BookFilterSet(FilterSet):
-        model = Book
-        fields = [
-            'binding',
-            ('genre', dict(order_by_count=True))
-        ]
-
-See :doc:`the Filters documentation <filters>` for options that can be
-specified. See :doc:`the FilterSet documentation <filterset>` for ways to
-customize the rendering of the filters.
+Customisation of the filters can be done in various ways - see :doc:`the
+FilterSet documentation <filterset>` for how to do this, and :doc:`the Filters
+documentation <filters>` for options that can be specified.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.