Django Tables 2

2.9.0 · active · verified Sun Apr 12

django-tables2 is a robust Django app designed for creating dynamic HTML tables with features like sorting, pagination, and custom column rendering. It helps streamline the display of complex data in a structured, user-friendly format within Django projects. The current version is 2.9.0, with a release cadence that generally follows Django's development cycle and feature enhancements.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `django-tables2` into a minimal Django project. It defines a simple model, creates a `Table` subclass with a `LinkColumn`, uses `SingleTableView` to fetch and display data, and renders it using the `render_table` template tag with a Bootstrap 4 theme. The example uses an in-memory SQLite database and creates temporary files for a fully self-contained, runnable setup.

import os
import django
from django.conf import settings
from django.urls import path
from django.http import HttpResponse
from django.db import models

# Minimal Django setup for a self-contained quickstart
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
if not settings.configured:
    settings.configure(
        DEBUG=True,
        SECRET_KEY='a-very-secret-key-for-dev-environment',
        ROOT_URLCONF=__name__,
        INSTALLED_APPS=[
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'django_tables2',
        ],
        TEMPLATES=[
            {
                'BACKEND': 'django.template.backends.django.DjangoTemplates',
                'DIRS': [os.path.dirname(__file__)], # Look for templates in the same directory
                'APP_DIRS': True,
                'OPTIONS': {
                    'context_processors': [
                        'django.template.context_processors.debug',
                        'django.template.context_processors.request',
                        'django.contrib.auth.context_processors.auth',
                        'django.contrib.messages.context_processors.messages',
                    ],
                },
            },
        ],
        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
        STATIC_URL='/static/',
    )
django.setup()

# 1. Define a simple Django model
class Person(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    city = models.CharField(max_length=100)

    class Meta:
        app_label = 'myapp' # Required for in-memory models setup

    def __str__(self):
        return self.name

# Simulate migrations for in-memory DB
from django.core.management import call_command
call_command('migrate', verbosity=0, interactive=False)

# Create some initial data
if not Person.objects.exists():
    Person.objects.create(name='Alice', age=30, city='New York')
    Person.objects.create(name='Bob', age=24, city='London')
    Person.objects.create(name='Charlie', age=35, city='Paris')

# 2. Define a Table class
from django_tables2 import Table, LinkColumn
from django.db.models import A # for LinkColumn accessor

class PersonTable(Table):
    name = LinkColumn('person_detail', args=[("pk", A("pk"))]) # Example LinkColumn

    class Meta:
        model = Person
        template_name = "django_tables2/bootstrap4.html" # Use a built-in template
        fields = ("name", "age", "city")
        order_by = ("name",) # Default ordering

# 3. Define a Django View
from django_tables2.views import SingleTableView

class PeopleView(SingleTableView):
    model = Person
    table_class = PersonTable
    template_name = 'people_list.html'

# Simple detail view for the LinkColumn example
def person_detail_view(request, pk):
    try:
        person = Person.objects.get(pk=pk)
        return HttpResponse(f"<h1>Detail for {person.name}</h1><p>Age: {person.age}, City: {person.city}</p><p><a href='/people/'>Back to list</a></p>")
    except Person.DoesNotExist:
        return HttpResponse("Person not found", status=404)

# 4. Define URLs
urlpatterns = [
    path('people/', PeopleView.as_view(), name='people_list'),
    path('people/<int:pk>/', person_detail_view, name='person_detail'),
]

# 5. Create a temporary template file (people_list.html)
_template_content = """
{% load render_table from django_tables2 %}
<!DOCTYPE html>
<html>
<head>
    <title>People List</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <h1>People</h1>
        {% render_table table %}
    </div>
</body>
</html>
"""

# Save the template content to a file for the quickstart to run
with open('people_list.html', 'w') as f:
    f.write(_template_content)

# Verify the table can be initialized and rendered into context
from django.test import RequestFactory
request_factory = RequestFactory()
request = request_factory.get('/people/')

# Call the view directly to get the response and context data
response = PeopleView.as_view()(request)
# Render the response to populate context_data for SingleTableView
response.render()

context = response.context_data
assert 'table' in context
assert isinstance(context['table'], PersonTable)

print("django-tables2 quickstart setup successful! Table initialized and rendered context contains table object.")

# Clean up the temporary template file
os.remove('people_list.html')

view raw JSON →