django-admin-sortable2
django-admin-sortable2 is a Django package that provides generic drag-and-drop ordering functionality for objects in the List, Stacked-Inline, and Tabular-Inline Views of the Django Admin interface. It enriches existing `ModelAdmin` and `InlineModelAdmin` classes with sortable behavior via mixins. The library is actively maintained, with frequent minor and patch releases to support newer Django and Python versions.
Warnings
- breaking Version 2.0 introduced significant breaking changes, including replacing jQuery-UI with Sortable.js, removing extended Django admin templates, and dropping support for older Django (<=3.2) and Python (2.7, 3.4, 3.5) versions. Projects upgrading from 1.x must thoroughly review their code and update dependencies.
- gotcha The model that you wish to make sortable must include a `PositiveIntegerField` for ordering (e.g., `order`) with `default=0`. This field must be the first element in the model's `Meta.ordering` tuple or list. For optimal performance, add `db_index=True`, and ensure it is not set to `editable=False`.
- gotcha When applying `django-admin-sortable2` to existing models, the `order` field for existing objects might be `0` or `null`, preventing proper sorting.
- gotcha When reordering items within `StackedInline` or `TabularInline` views, the changes are not immediately saved to the database. The new order will only persist after the parent model's form is explicitly saved.
- gotcha If you use a custom `formset` for your `SortableInlineAdminMixin` (e.g., `SortableTabularInline` or `SortableStackedInline`), that custom formset must inherit from `adminsortable2.admin.CustomInlineFormSet` in addition to `BaseInlineFormSet` to ensure sorting functionality works correctly.
Install
-
pip install django-admin-sortable2
Imports
- SortableAdminMixin
from adminsortable2.admin import SortableAdminMixin
- SortableInlineAdminMixin
from adminsortable2.admin import SortableInlineAdminMixin
- CustomInlineFormSet
from adminsortable2.admin import CustomInlineFormSet
Quickstart
import os
# settings.py
# INSTALLED_APPS = [
# ...,
# 'adminsortable2',
# 'your_app_name',
# ]
# your_app_name/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
order = models.PositiveIntegerField(default=0, blank=False, null=False, db_index=True)
class Meta:
ordering = ['order']
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
class Item(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
order = models.PositiveIntegerField(default=0, blank=False, null=False, db_index=True)
class Meta:
ordering = ['order']
def __str__(self):
return self.name
# your_app_name/admin.py
from django.contrib import admin
from adminsortable2.admin import SortableAdminMixin, SortableTabularInline
from .models import Category, Item
class ItemInline(SortableTabularInline):
model = Item
extra = 1
fields = ['name', 'order'] # 'order' can be omitted from 'fields' to be hidden
@admin.register(Category)
class CategoryAdmin(SortableAdminMixin, admin.ModelAdmin):
list_display = ['name', 'order']
inlines = [ItemInline]
# To run the example (after creating a Django project):
# 1. Add 'adminsortable2' and 'your_app_name' to INSTALLED_APPS in settings.py.
# 2. Run: python manage.py makemigrations your_app_name
# 3. Run: python manage.py migrate
# 4. Run: python manage.py createsuperuser
# 5. Run: python manage.py runserver
# 6. Access /admin/ and navigate to 'Categories' to test sorting.