Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom filters, extra data rows, more formatting #26

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/clientside.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Client-side processing
======================

Django ezTables also provides a way for users to grab data from a server, using
the DataTables API, but also defer all processing to the client-side. In order
to do this, the user must still define a DataTables view as in the :ref:`Server-side
processing <serverside>` section, however, he/she must set the DataTables `serverSide
<https://datatables.net/reference/option/serverSide>`_ option to ``false``, or
not set it at all.

**Note:** Users that choose this option can still format and add extra data on
the server side.
7 changes: 5 additions & 2 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ Features
========

- Datatables.net, plugins and localization integration with Django.
- Server-side processing with a simple view supporting:
- Easy switch between Server-side processing and Client-side proecessing, with
a simple view supporting:
- sorting (single and multi columns)
- filtering with regex support (global and by column)
- filtering with regex support (custom, global and by column)
- formatting using format pattern
- context data for each row (not using the DataTables API)
- Deferred loading support.
- Twitter Bootstrap integration.

Expand Down Expand Up @@ -75,6 +77,7 @@ Documentation

templatetags
serverside
clientside
localization
integration
api
Expand Down
144 changes: 138 additions & 6 deletions doc/serverside.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _serverside:

Server-side processing
======================

Expand All @@ -10,7 +12,7 @@ As it extends :class:`django.views.generic.list.MultipleObjectMixin` it expects

Both modes expect a ``fields`` attribute that can optionnaly contains format patterns.

The exemple will use the same models as the demo:
The example will use the same models as the demo:

.. code-block:: python

Expand Down Expand Up @@ -57,7 +59,7 @@ To render an array-based JSON, you must provide ``fields`` as a ``list`` or a `
)


You can simply instanciate your datatable with:
You can simply instantiate your datatable with:

.. code-block:: javascript

Expand Down Expand Up @@ -115,8 +117,13 @@ You need to use the ``aoColumns`` properties in the DataTables initialization:
});


Formatting
----------

There are two main ways to format the data:

Format patterns
---------------
~~~~~~~~~~~~~~~

You can optionally provide some format patterns in the field definition:

Expand Down Expand Up @@ -145,6 +152,23 @@ You can optionally provide some format patterns in the field definition:
'css_grade': 'engine__css_grade',
}

Format functions
~~~~~~~~~~~~~~~~

You can define your own format function (class method) in your DataTablesView
class. By default, Django ezTables will look for one of the following function
and call it, if it exists:

.. code-block:: python

def format_data_rows(self, rows)
def format_data_row(self, row)

The first method reads a list of table rows (which will be in ``tuple`` or
``dict`` format, depending on your ``fields`` format) and should return a
formatted list of table rows. The second method is called for every row of the
data and should return a formatted table row.


Custom sort
-----------
Expand All @@ -166,10 +190,10 @@ It takes the requested direction (``''`` or ``'-'``) as a parameter and should r
'''Sort on name and platform instead of platform'''
return ('%sname' % direction, '%splatform' % direction)

Custom search
-------------
Custom Column search
--------------------

You can implement a custom search method.
You can implement a custom column search method.
It has to be named ``search_col_X`` where ``X`` should be the index given by the datatables request (correspond to the filtered column).

It takes the search term and the queryset to filter as a parameter and should return the filtered queryset.
Expand All @@ -182,6 +206,114 @@ It takes the search term and the queryset to filter as a parameter and should re
'''Search on version instead of name'''
return queryset.filter(version__icontains=search)

Custom filters
--------------

The user can add his/her own filter classes in the ``filters`` field of the
DatatablesView class or define one or more ``filter_*`` methods in this class.
The latter way is similar to the custom sorting approach.

The former way is a bit more flexible and can integrate with the popular
`django-filter <https://github.com/alex/django-filter>`_ plugin. More
specifically, filters added in the `filters` field must have one of the
following formats:

* List format: [filter1, filter2, filter3]
Note that this format requires that the filters have a `name`
attribute and a `filter` method.

.. code-block:: python

class Filter(object):
name = "platform"
def filter(self, search, queryset)
return queryset.filter(platform__icontaints=search)
filter_platform = Filter()

class BrowserDatatablesView(DatatablesView):
model = Browser
fields = (
'engine__name',
'name',
'platform',
'engine__version',
'engine__css_grade',
)
filters = [filter_platform]

* Dict format: {'name1': filter1, 'name2': filter2, 'name3': filter3}
Note that this format requires that the filters have a `filter`
method.

.. code-block:: python

class Filter(object):
def filter(self, search, queryset)
return queryset.filter(platform__icontaints=search)
filter_platform = Filter()

class BrowserDatatablesView(DatatablesView):
model = Browser
fields = (
'engine__name',
'name',
'platform',
'engine__version',
'engine__css_grade',
)
filters = {'platform': filter_platform}

* Django-filter FilterSet format: Simply a FilterSet class

.. code-block:: python

import django_filters

class BrowserFilterSet(django_filters.FilterSet)
class Meta:
model = Browser
fields = ('platform')

class BrowserDatatablesView(DatatablesView):
model = Browser
fields = (
'engine__name',
'name',
'platform',
'engine__version',
'engine__css_grade',
)
filters = BrowserFilterSet

In order to trigger a filter, its name must match the asterisk part of a
Datatables "sSearch_*" argument. The value of this argument will be
considered as the query for this filter.

Also, note that all list/dict filters should take as an argument a query and a
queryset and return a filtered queryset.

Extra data
----------

This optional feature allows the user to extract extra data for each table row,
without showing them on the table. Extra data can come in handy when you want
to provide more context/info for each table row, but you don't want to show it
as a main column.

In order to extract extra data for each row, you must define the following
function in your DataTablesView class:

.. code-block:: python

def get_extra_data_row(self, instance)

This function will receive a model instance as its only argument. The user can
use this instance to extract more info from it, e.g. fields such as dates,
which are typically large for a table column. The returned info for each row
can be arbitrary, since it's not handled by either DataTables or Django
ezTables, but from the client-side code. The only thing that Django ezTables
will do is add in the standard DataTables JSON response an ``extra`` list,
which will have the produced info for each table row.

SQLite Warnings
---------------
Expand Down
23 changes: 23 additions & 0 deletions eztables/test_array_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,33 @@
CustomBrowserDatatablesView,
SpecialCaseDatatablesView,
)
from eztables.tests import (
ExtraBrowserDatatablesViewAll,
ExtraBrowserDatatablesViewRow,
UserFormatRowBrowserDatatablesView,
FilterFunctionBrowserDatatablesView,
FilterListBrowserDatatablesView,
FilterDictBrowserDatatablesView,
FilterSetBrowserDatatablesView,
)


urlpatterns = patterns('',
url(r'^$', BrowserDatatablesView.as_view(), name='browsers'),
url(r'^formatted/$', FormattedBrowserDatatablesView.as_view(), name='formatted-browsers'),
url(r'^custom/$', CustomBrowserDatatablesView.as_view(), name='custom-browsers'),
url(r'^special/$', SpecialCaseDatatablesView.as_view(), name='special'),
url(r'^extra/$', ExtraBrowserDatatablesViewAll.as_view(), name='extra'),
url(r'^extra_row/$', ExtraBrowserDatatablesViewRow.as_view(),
name='extra_row'),
url(r'^format_row/$', UserFormatRowBrowserDatatablesView.as_view(),
name='format_row'),
url(r'^filter_function/$', FilterFunctionBrowserDatatablesView.as_view(),
name='filter_function'),
url(r'^filter_list/$', FilterListBrowserDatatablesView.as_view(),
name='filter_list'),
url(r'^filter_dict/$', FilterDictBrowserDatatablesView.as_view(),
name='filter_dict'),
url(r'^filter_set/$', FilterSetBrowserDatatablesView.as_view(),
name='filter_set'),
)
24 changes: 24 additions & 0 deletions eztables/test_object_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,34 @@
CustomObjectBrowserDatatablesView,
SpecialCaseDatatablesView,
)
from eztables.tests import (
ExtraObjectBrowserDatatablesViewAll,
ExtraObjectBrowserDatatablesViewRow,
UserFormatRowObjectBrowserDatatablesView,
FilterFunctionObjectBrowserDatatablesView,
FilterListObjectBrowserDatatablesView,
FilterDictObjectBrowserDatatablesView,
FilterSetObjectBrowserDatatablesView,
)

urlpatterns = patterns('',
url(r'^$', ObjectBrowserDatatablesView.as_view(), name='browsers'),
url(r'^formatted/$', FormattedObjectBrowserDatatablesView.as_view(), name='formatted-browsers'),
url(r'^custom/$', CustomObjectBrowserDatatablesView.as_view(), name='custom-browsers'),
url(r'^special/$', SpecialCaseDatatablesView.as_view(), name='special'),
url(r'^extra/$', ExtraObjectBrowserDatatablesViewAll.as_view(),
name='extra'),
url(r'^extra_row/$', ExtraObjectBrowserDatatablesViewRow.as_view(),
name='extra_row'),
url(r'^format_row/$', UserFormatRowObjectBrowserDatatablesView.as_view(),
name='format_row'),
url(r'^filter_function/$',
FilterFunctionObjectBrowserDatatablesView.as_view(),
name='filter_function'),
url(r'^filter_list/$', FilterListObjectBrowserDatatablesView.as_view(),
name='filter_list'),
url(r'^filter_dict/$', FilterDictObjectBrowserDatatablesView.as_view(),
name='filter_dict'),
url(r'^filter_set/$', FilterSetObjectBrowserDatatablesView.as_view(),
name='filter_set'),
)
Loading