django-admin-sortable2

repository·master·Indexed 21 days ago

https://github.com/jrief/django-admin-sortable2

A library providing drag-and-drop reordering capabilities for Django Admin List, StackedInline, and TabularInline views using Sortable.JS. It utilizes mixin classes to enrich admin classes without requiring changes to the model's base class. Features include group sorting, cross-page sorting via admin actions, and a 'reorder' management command to restore primary ordering fields.

Tokens
5K
Snippets
14
Records
20
Agent score
73%

What's inside django-admin-sortable2

  1. Overview of django-admin-sortable2

    master

    django-admin-sortable2 is a generic drag-and-drop ordering package designed to sort objects within the list- and detail-views of the Django admin interface.

    Instead of requiring models to inherit from a specific base class, this package uses mixin classes to enrich existing classes derived from:

    • admin.ModelAdmin
    • admin.StackedInline
    • admin.TabularInline

    This mixin approach allows for easy integration into existing projects with minimal code modification.

  2. Avoid using unique indices on ordering fields

    master

    It is strongly advised not to set unique=True on the position/ordering field. While it might seem desirable, it causes significant issues with database portability:

    • MySQL: Requires an ORDER BY clause in bulk updates on unique fields.
    • SQLite: Has bugs regarding bulk updates on unique fields and transaction handling.
    • PostgreSQL: Handles it correctly by updating in one transaction and rebuilding the index, but this makes your code non-portable to other databases.

    To maintain database portability, avoid unique=True on the ordering field.

  3. Sort objects in Django admin list views

    master

    The package provides an intuitive way to sort rows in the Django admin list view:

    • Drag-and-drop: You can drag rows using a dedicated draggable area in one of the columns.
    • Group sorting: You can select multiple rows using checkboxes and sort them as a group.
    • Cross-page sorting: To sort rows across different pagination pages, select the rows using checkboxes and use a Django Admin action to move them to a different page.
  4. Integrate drag-and-drop ordering using mixins

    master

    The library provides simple mixin classes designed to enrich existing Django Admin classes. You can integrate drag-and-drop functionality into:

    • Any class inheriting from admin.ModelAdmin
    • Any class inheriting from admin.StackedInline
    • Any class inheriting from admin.TabularInline

    Because it uses mixins, you do not need to change your model's base class; existing models inheriting from models.Model (or other derivatives) are fully compatible without special configuration.

  5. Build the JavaScript client from source

    master

    If you are installing the project directly from GitHub, you must build the JavaScript client using the esbuild TypeScript compiler. This requires NodeJS 18+.

    Building the client generates the bundled JavaScript file at adminsortable2/static/adminsortable2/js/adminsortable2.min.js, which is used by the sortable-admin mixin classes. You can also build an unminimized version with sourcemaps for debugging.

    git clone https://github.com/jrief/django-admin-sortable2.git
    cd django-admin-sortable2
    npm install --include=dev
    npm run build
    
    # For an unminimized version including a sourcemap:
    npm run build -- --debug
  6. Create a data migration to reorder existing items

    master

    Alternatively, you can use a Django data migration to set the ordering values. This is useful for a one-time setup immediately after adding the ordering field.

    1. Create an empty migration: ./manage.py makemigrations myapp.
    2. Edit the migration file to include a reorder function that enumerates the objects and assigns the order value.
    3. Use migrations.RunPython to execute the function, providing reverse_code=migrations.RunPython.noop to ensure the migration is reversible without error.
    def reorder(apps, schema_editor):
        MyModel = apps.get_model("myapp", "MyModel")
        for order, item in enumerate(MyModel.objects.all(), 1):
            item.my_order = order
            item.save(update_fields=['my_order'])
    
    class Migration(migrations.Migration):
        operations = [
            ...
            migrations.RunPython(reorder, reverse_code=migrations.RunPython.noop),
        ]
  7. Run the django-admin-sortable2 demo app

    master

    The project includes a testapp demo that implements all features of django-admin-sortable2. It is recommended to use this demo to verify bugs or test new features.

    Running the demo requires Python and NodeJS. The setup involves building the JS client, installing dependencies, and patching Django's default admin templates to ensure compatibility with the library's sorting logic.

    git clone https://github.com/jrief/django-admin-sortable2.git
    cd django-admin-sortable2
    npm install --include=dev
    npm run build
    npm run minify
    python -m pip install Django
    python -m pip install -r testapp/requirements.txt
    
    # Patching Django templates
    django_version=$(python -c 'from django import VERSION; print("{0}.{1}".format(*VERSION))')
    mkdir adminsortable2/templates/adminsortable2/edit_inline
    curl --no-progress-meter --output adminsortable2/templates/adminsortable2/edit_inline/stacked-django-$django_version.html https://raw.githubusercontent.com/django/django/stable/$django_version.x/django/contrib/admin/templates/admin/edit_inline/stacked.html
    curl --no-progress-meter --output adminsortable2/templates/adminsortable2/edit_inline/tabular-django-$django_version.html https://raw.githubusercontent.com/django/django/stable/$django_version.x/django/contrib/admin/templates/admin/edit_inline/tabular.html
    patch -p0 adminsortable2/templates/adminsortable2/edit_inline/stacked-django-$django_version.html patches/stacked-django-4.0.patch
    patch -p0 adminsortable2/templates/adminsortable2/edit_inline/tabular-django-$django_version.html patches/tabular-django-4.0.patch
    
    # Start the app
    cd testapp
    ./manage.py migrate
    ./manage.py loaddata fixtures/data.json
    ./manage.py runserver
  8. Run unit and end-to-end tests

    master

    The project uses pytest-django for unit tests and Playwright-Python for end-to-end tests. To run the full test suite, you must install the Playwright browsers and dependencies, patch the Django templates as described in the demo setup, and then run pytest.

    git clone https://github.com/jrief/django-admin-sortable2.git
    cd django-admin-sortable2
    npm install --include=dev
    npm run build
    python -m pip install Django
    python -m pip install -r testapp/requirements.txt
    python -m playwright install
    python -m playwright install-deps
    
    # Patching Django templates
    django_version=$(python -c 'from django import VERSION; print("{0}.{1}".format(*VERSION))')
    mkdir adminsortable2/templates/adminsortable2/edit_inline
    curl --no-progress-meter --output adminsortable2/templates/adminsortable2/edit_inline/stacked-django-$django_version.html https://raw.githubusercontent.com/django/django/stable/$django_version.x/django/contrib/admin/templates/admin/edit_inline/stacked.html
    curl --no-progress-meter --output adminsortable2/templates/adminsortable2/edit_inline/tabular-django-$django_version.html https://raw.githubusercontent.com/django/django/stable/$django_version.x/django/contrib/admin/templates/admin/edit_inline/tabular.html
    patch -p0 adminsortable2/templates/adminsortable2/edit_inline/stacked-django-$django_version.html patches/stacked-django-4.0.patch
    patch -p0 adminsortable2/templates/adminsortable2/edit_inline/tabular-django-$django_version.html patches/tabular-django-4.0.patch
    
    # Run tests
    python -m pytest testapp