Django REST Framework Datatables
This package provides seamless integration between Django REST framework and Datatables. It automatically handles searching, filtering, ordering, and pagination for your DRF API endpoints when requested with the `?format=datatables` parameter. The library, currently at version 0.7.2, maintains an active development status with regular updates to support newer versions of Django, DRF, and Python.
Common errors
-
DataTables warning: table id=<your-table-id> - Ajax error
cause The API endpoint is not returning data in the expected Datatables JSON format, often because the `?format=datatables` query parameter is missing or the DRF settings are incorrect.fixVerify that `rest_framework_datatables` is in `INSTALLED_APPS` and `REST_FRAMEWORK` settings are correctly configured with `DatatablesRenderer`, `DatatablesFilterBackend`, and `DatatablesPageNumberPagination`. Crucially, ensure your Datatables AJAX URL includes `?format=datatables`. -
TypeError: __init__() takes 1 positional argument but 2 were given (or similar TypeErrors in ViewSets)
cause This often occurs if a DRF `ViewSet` is incorrectly wired in `urls.py`, especially if using `as_view()` without specifying HTTP method mappings, or if directly passing the ViewSet class instead of its `.as_view()` result to a URL pattern.fixEnsure your `urls.py` correctly maps HTTP methods to ViewSet actions, e.g., `path('your-api/', YourViewSet.as_view({'get': 'list'}), name='your-view')` when not using a router, or use a `routers.DefaultRouter()` to automatically handle URL patterns for `ModelViewSet`s. -
Table displays, but searching, filtering, or sorting does not work.
cause The `DatatablesFilterBackend` might not be correctly configured in `REST_FRAMEWORK` settings, or there's an issue with how Datatables is sending the search/order parameters (e.g., `data-name` attributes on columns).fixConfirm `DatatablesFilterBackend` is listed in `DEFAULT_FILTER_BACKENDS` in `settings.py`. For custom columns, ensure `data-name` (in HTML) or `columns[N].name` (in JS config) attributes are correctly set to the serializer field names for `djangorestframework-datatables` to identify which fields to filter/sort on. If using `django-filter`, ensure the correct `DatatablesFilterBackend` from `rest_framework_datatables.django_filters.backends` is used.
Warnings
- gotcha Failing to append `?format=datatables` to your API URL when making requests from Datatables JavaScript will cause an 'Ajax error' in Datatables. The library requires this parameter to format the response correctly.
- gotcha When integrating with `django-filter`, the import paths for `DatatablesFilterBackend` and `DatatablesFilterSet` change to use the `django_filters` subpackage. Importing from the top-level `filters` module will not provide the enhanced functionality.
- gotcha Column names in your Datatables JavaScript configuration (`data` or `name` properties) must exactly match the fields exposed by your DRF serializer. Mismatches lead to empty columns or 'Ajax error'.
Install
-
pip install djangorestframework-datatables
Imports
- DatatablesRenderer
from rest_framework_datatables.renderers import DatatablesRenderer
- DatatablesFilterBackend
from rest_framework_datatables.filters import DatatablesFilterBackend
- DatatablesPageNumberPagination
from rest_framework_datatables.pagination import DatatablesPageNumberPagination
- DatatablesLimitOffsetPagination
from rest_framework_datatables.pagination import DatatablesLimitOffsetPagination
- DatatablesFilterBackend (for django-filter)
from rest_framework_datatables.filters import DatatablesFilterBackend
from rest_framework_datatables.django_filters.backends import DatatablesFilterBackend
- DatatablesFilterSet
from rest_framework_datatables.django_filters.filterset import DatatablesFilterSet
Quickstart
import os
import django
from django.conf import settings
from django.urls import path, include
from django.db import models
from rest_framework import serializers, viewsets, routers
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
# Minimal Django settings for demonstration
if not settings.configured:
settings.configure(
INSTALLED_APPS=[
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'rest_framework',
'rest_framework_datatables' # Add this line
],
DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
ROOT_URLCONF=__name__,
SECRET_KEY='a-very-secret-key',
REST_FRAMEWORK={
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
'rest_framework_datatables.renderers.DatatablesRenderer', # Add this renderer
),
'DEFAULT_FILTER_BACKENDS': (
'rest_framework_datatables.filters.DatatablesFilterBackend', # Add this filter backend
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesPageNumberPagination',
'PAGE_SIZE': 10,
}
)
django.setup()
# 1. Define a simple Django model
class Item(models.Model):
name = models.CharField(max_length=100)
value = models.IntegerField()
def __str__(self):
return self.name
# 2. Define a DRF Serializer
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ['id', 'name', 'value']
# 3. Define a DRF ViewSet
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
# 4. Register the ViewSet with a router
router = routers.DefaultRouter()
router.register(r'items', ItemViewSet)
# 5. Define URL patterns
urlpatterns = [
path('api/', include(router.urls)),
]
# Example usage (simulate data and API call)
if __name__ == '__main__':
# Create some dummy data
Item.objects.create(name='Apple', value=10)
Item.objects.create(name='Banana', value=20)
Item.objects.create(name='Cherry', value=30)
print("Configuration done. Your API endpoint is '/api/items/'.")
print("To get Datatables-compatible output, append '?format=datatables'.")
print("Example API call: http://localhost:8000/api/items/?format=datatables")
print("Start a Django dev server and navigate to the URL to see output.")
# In a real Django project, you would run:
# python manage.py makemigrations
# python manage.py migrate
# python manage.py runserver