Skip to main content

Django Scotty

CI Python Versions License Ruff

Advanced table views for Django with CRUD operations, filtering, export, and htmx-powered modals.

Built on top of django-tables2, django-filter, and django-cotton.


Features

  • CRUD Views — Ready-to-use Create, Read, Update, Delete views with a consistent look
  • Table Views — Filterable, sortable, paginated table views via django-tables2
  • Filtering — Integrated django-filters with Bootstrap 5 UI
  • Export to Excel — One-click export to XLSX via tablib
  • htmx Modals — Create/Update forms in modals with zero custom JS
  • Pagination Fix — Invalid page numbers redirect gracefully instead of 404/500
  • Bulk Actions — Define custom actions on table rows
  • Modern UI — django-cotton components + Bootstrap 5 + crispy-forms

Requirements

  • Python >= 3.12
  • Django >= 5.1 (via django-cotton constraint)
  • django-cotton >= 2.1
  • django-tables2 >= 2.7
  • django-filter >= 25.1
  • django-crispy-forms >= 2.4 + crispy-bootstrap5
  • tablib >= 3.8 (with XLSX support)

Installation

pip install django-scotty

Or with uv:

uv pip install django-scotty

Add the required apps to INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "django_cotton",
    "django_tables2",
    "django_filters",
    "django_scotty",
    ...
]

Quick Start

List View (table)

# views.py
import django_tables2 as tables
from django_scotty.views import CottonTableView
from .models import Product


class ProductTable(tables.Table):
    class Meta:
        model = Product
        fields = ["name", "price", "stock", "category"]


class ProductListView(CottonTableView):
    model = Product
    table_class = ProductTable
    title = "Products"
    paginate_by = 25
# urls.py
from django.urls import path
from .views import ProductListView

urlpatterns = [
    path("products/", ProductListView.as_view(), name="product-list"),
]

Create View

from django_scotty.views import GenericCreateView
from .models import Product
from .forms import ProductForm


class ProductCreateView(GenericCreateView):
    model = Product
    form_class = ProductForm
    title_form = "New Product"

Update View

from django_scotty.views import GenericUpdateView


class ProductUpdateView(GenericUpdateView):
    model = Product
    form_class = ProductForm
    title_form = "Edit Product"

Delete View

from django_scotty.views import GenericDeleteView


class ProductDeleteView(GenericDeleteView):
    model = Product

Detail View

from django_scotty.views import GenericDetailView


class ProductDetailView(GenericDetailView):
    model = Product

URL auto-discovery

For a cleaner setup, gather all views from a scotty/ directory in your app:

# urls.py
from django_scotty.urls import load_scotty_urls, add_urls
from myapp import scotty

urlpatterns = [
    *add_urls([scotty]),
]

# or auto-discover from an app:
urlpatterns = [
    *load_scotty_urls("myapp"),
]

Filtering

Add a FilterSet and wire it to your list view:

import django_filters


class ProductFilter(django_filters.FilterSet):
    class Meta:
        model = Product
        fields = {
            "name": ["exact", "icontains"],
            "category": ["exact"],
            "price": ["gte", "lte"],
        }


class ProductListView(CottonTableView):
    model = Product
    table_class = ProductTable
    filterset_class = ProductFilter
    paginate_by = 25

htmx Modal Forms

GenericCreateView and GenericUpdateView render inside an htmx-powered Bootstrap modal by default when the request includes the HX-Request header.

On success, they return an HX-Refresh response that tells the parent page to reload the table. No JavaScript required beyond the htmx library.

class ProductCreateView(GenericCreateView):
    model = Product
    form_class = ProductForm
    title_form = "New Product"
    auto_forms_buttons = True  # adds Save / Cancel buttons automatically

Export

Every CottonTableView includes a built-in "Export to XLSX" button. The export uses tablib and respects the current filter/sort state.

Customize the filename:

class ProductListView(CottonTableView):
    model = Product
    table_class = ProductTable
    export_name = "products_report"  # default: slugified model name

Configuration

Set SCOTTY_CONFIG in your Django settings:

SCOTTY_CONFIG = {
    "BUTTON_VARIANT": "primary",       # default button variant
    "BUTTON_VARIANT_DANGER": "danger", # delete button variant
    "BUTTON_STYLE": "solid",           # solid (filled) or outline
}

Available variants: primary, secondary, success, danger, warning, info, light, dark.


Development

Setup

# Clone the repo
git clone https://github.com/jmschillaci/django-scotty.git
cd django-scotty

# Install with dev dependencies
uv sync --group dev

Run tests

# Full suite
uv run pytest -v --cov=src/django_scotty

# With tox (requires tox and the Python versions installed)
tox
tox -e lint        # ruff checks only
tox -e type        # mypy only
tox -e py312       # tests on Python 3.12 only

Lint & type check

uv run ruff check src/django_scotty tests
uv run ruff format --check src/django_scotty tests
uv run mypy src/django_scotty

Requirements

Full dependency list in pyproject.toml.

Dependency Minimum Version
Python 3.12
Django 5.1+
django-cotton 2.1
django-tables2 2.7
django-filter 25.1
django-crispy-forms 2.4
crispy-bootstrap5 2024.10
tablib[xlsx] 3.8
django-htmx 1.26

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing)
  3. Add tests for your changes
  4. Ensure all checks pass (uv run pytest, uv run mypy, uv run ruff check)
  5. Submit a Pull Request

License

MIT — see LICENSE.


Credits

Built with:

Release files for django-scotty 0.5.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-scotty 0.5.3
File Size Uploaded
django_scotty-0.5.3.tar.gz 25.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-scotty 0.5.3
File Interpreter ABI Platform
django_scotty-0.5.3-py3-none-any.whl Python 3 none any Details

Total release size: 64.5 kB

Release files / django_scotty-0.5.3.tar.gz

Download URL django_scotty-0.5.3.tar.gz
Size 25.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3f42dcd673ca6956197b40a8a4add22be7fff2b7d8ec6b88b953b6959eb83cf0
BLAKE2b-256 checksum
How to use checksums
919b73a0b48ff79c0d770df2f8551c2ef51340d7de0f3e1e3fa9f1288361d41e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.5

Release files / django_scotty-0.5.3-py3-none-any.whl

Download URL django_scotty-0.5.3-py3-none-any.whl
Size 38.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6d0788c0a07f5a3f41793a6f077f1dce72758cec446e5ef17690771ff6e0818
BLAKE2b-256 checksum
How to use checksums
c8e446853aeffdbec89f69238e8c7d4a596bdcbaf293116685fdb39f061fa15a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.5

Release history Release notifications | RSS feed

This release

0.5.3 This release

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page