
About
django-datatables-view is a base view for handling server side processing for the awesome datatables 1.9.x,
1.10.x (http://datatables.net).
django-datatables-view simplifies handling of sorting, filtering and creating JSON output, as defined
at: http://datatables.net/examples/server_side/
Example
Example project that uses django-datatables-view is available
at: https://bitbucket.org/pigletto/django-datatables-view-example/
Usage
1. Install django-datatables-view
pip install django-datatables-view
2. Edit views.py
django_datatables_view uses GenericViews, so your view should just inherit from base class: BaseDatatableView,
and override few things
(there is also a DatatableMixin - pure datatables handler that can be used with the mixins of your choice, eg.
django-braces). These are:
- model - the model that should be used to populate the datatable
- columns - the columns that are going to be displayed. If not defined then django_datatables_view will look for '
data' or 'name' in the columns definition provided in the request by DataTables, eg.:
columns: [{data: 'first_name'}] (only works for datatables 1.10+)
- order_columns - list of column names used for sorting (e.g. if user sorts by second column then second column name
from this list will be used with order by clause). If not defined then django_datatables_view will look for 'data'
or 'name' in the columns definition provided in the request by DataTables, eg.: columns: [{data: 'first_name'}] (only
works for datatables 1.10+)
- filter_queryset - if you want to filter your DataTable in some specific way then override this method. In case of
older DataTables (pre 1.10) you need to override this method or there will be no filtering.
- filter_method - returns 'istartswith' by default, you can override it to use different filtering method, e.g.
icontains: return self.FILTER_ICONTAINS
For more advanced customisation you might want to override:
- get_initial_queryset - method that should return queryset used to populate datatable
- prepare_results - this method should return list of lists (rows with columns) as needed by datatables
- escape_values - you can set this attribute to False in order to not escape values returned from render_column
method
The code is rather simple so do not hesitate to have a look at it. Method that is executed first (and that calls other
methods to execute whole logic) is get_context_data. Definitely have a look at this method!
See example below:
from django_datatables_view.base_datatable_view import BaseDatatableView
from django.utils.html import escape
class OrderListJson(BaseDatatableView):
model = MyModel
columns = ['number', 'user', 'state', 'created', 'modified']
order_columns = ['number', 'user', 'state', '', '']
max_display_length = 500
def render_column(self, row, column):
if column == 'user':
return escape('{0} {1}'.format(row.customer_firstname, row.customer_lastname))
else:
return super(OrderListJson, self).render_column(row, column)
def filter_queryset(self, qs):
search = self.request.GET.get('search[value]', None)
if search:
qs = qs.filter(name__istartswith=search)
filter_customer = self.request.GET.get('customer', None)
if filter_customer:
customer_parts = filter_customer.split(' ')
qs_params = None
for part in customer_parts:
q = Q(customer_firstname__istartswith=part) | Q(customer_lastname__istartswith=part)
qs_params = qs_params | q if qs_params else q
qs = qs.filter(qs_params)
return qs
3. Edit urls.py
Add typical django's urlconf entry:
url(r'^my/datatable/data/$', login_required(OrderListJson.as_view()), name='order_list_json'),
4. Define HTML + JavaScript
Example JS:
$(document).ready(function () {
var oTable = $('.datatable').dataTable({
"processing": true,
"serverSide": true,
"ajax": "{% url 'order_list_json' %}"
});
});
Another example of views.py customisation
from django_datatables_view.base_datatable_view import BaseDatatableView
from django.utils.html import escape
class OrderListJson(BaseDatatableView):
order_columns = ['number', 'user', 'state']
def get_initial_queryset(self):
return MyModel.objects.filter(something=self.kwargs['something'])
def filter_queryset(self, qs):
search = self.request.GET.get('search[value]', None)
if search:
qs = qs.filter(name__istartswith=search)
filter_customer = self.request.GET.get('customer', None)
if filter_customer:
customer_parts = filter_customer.split(' ')
qs_params = None
for part in customer_parts:
q = Q(customer_firstname__istartswith=part) | Q(customer_lastname__istartswith=part)
qs_params = qs_params | q if qs_params else q
qs = qs.filter(qs_params)
return qs
def prepare_results(self, qs):
json_data = []
for item in qs:
json_data.append([
escape(item.number),
escape("{0} {1}".format(item.customer_firstname, item.customer_lastname)),
item.get_state_display(),
item.created.strftime("%Y-%m-%d %H:%M:%S"),
item.modified.strftime("%Y-%m-%d %H:%M:%S")
])
return json_data
Yet another example of views.py customisation
This sample assumes that list of columns and order columns is defined on the client side (DataTables), eg.:
$(document).ready(function () {
var dt_table = $('.datatable').dataTable({
order: [[0, "desc"]],
columns: [
{
data: 'name',
orderable: true,
searchable: true
},
{
data: 'description',
orderable: true,
searchable: true,
}
],
searching: true,
processing: true,
serverSide: true,
stateSave: true,
ajax: TESTMODEL_LIST_JSON_URL
});
});
class TestModelListJson(BaseDatatableView):
model = TestModel