### Install django-admin-sortable2 Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/installation.md Use pip to install the package from PyPI. ```bash pip install django-admin-sortable2 ``` -------------------------------- ### Install django-admin-sortable2 Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Install the package using pip. Add 'adminsortable2' to your INSTALLED_APPS in settings.py. ```bash pip install django-admin-sortable2 ``` ```python # settings.py INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.admin', 'django.contrib.staticfiles', 'django.contrib.messages', 'adminsortable2', # ... your apps ] ``` -------------------------------- ### Run the demo application Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md Steps to set up the environment, patch Django templates, and start the development server for the demo application. ```bash 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 # we use the default template files and patch them, rather than using our own modified one 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 cd testapp ./manage.py migrate ./manage.py loaddata fixtures/data.json ./manage.py runserver ``` -------------------------------- ### Run the test suite Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md Commands to install dependencies and execute unit and end-to-end tests using pytest-django and Playwright. ```shell 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 ``` -------------------------------- ### Run Pytest for Testing Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md Executes the pytest test suite for the project. Ensure you have pytest installed. ```bash python -m pytest testapp ``` -------------------------------- ### Setup Django Admin Sortable2 Templates Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md This script fetches and patches default Django admin templates to integrate with django-admin-sortable2. It determines the Django version, creates necessary directories, downloads the correct template files, and applies patches. ```bash 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 ``` -------------------------------- ### Django ChoiceField Example Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md Demonstrates the correct usage of lists and tuples within a Django ChoiceField. The 'choices' attribute should be a list for potential extension, while its inner items (value-label pairs) must be tuples as they are fixed. ```python color = ChoiceField( label="Color", choices=[('ff0000', "Red"), ('00ff00', "Green"), ('0000ff', "Blue")], ) ``` -------------------------------- ### Prepopulate Ordering Fields via Management Command Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Use the provided management command to automatically populate ordering fields for existing model instances. ```bash shell> ./manage.py reorder my_app.ModelOne [my_app.ModelTwo ...] ``` -------------------------------- ### Build the JavaScript client Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/contributing.md Commands to clone the repository and build the JavaScript client using esbuild. Requires NodeJS 18+. ```shell 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, run npm run build -- --debug ``` -------------------------------- ### Create a sortable Stacked Inline admin (base class) Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md If only the inline model needs to be sortable and the parent model does not, use `SortableAdminBase` instead of `SortableAdminMixin`. ```python from django.contrib import admin from adminsortable2.admin import SortableAdminBase from myapp.models import Chapter class ChapterStackedInline(SortableStackedInline): model = Chapter extra = 1 @admin.register(Book) class SortableBookAdmin(SortableAdminBase, admin.ModelAdmin): ... inlines = [ChapterStackedInline] ``` -------------------------------- ### Configure INSTALLED_APPS Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/installation.md Add adminsortable2 to the INSTALLED_APPS list in your Django settings.py file. ```python INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.admin', 'django.contrib.staticfiles', 'django.contrib.messages', ... 'adminsortable2', ... ] ``` -------------------------------- ### Create Data Migration for Ordering Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Populate ordering fields for existing data during model migrations. ```python # migrations/0002_add_ordering.py from django.db import migrations, models def reorder(apps, schema_editor): """Populate ordering field with sequential values.""" Book = apps.get_model("myapp", "Book") for order, item in enumerate(Book.objects.all(), start=1): item.my_order = order item.save(update_fields=['my_order']) def reverse_reorder(apps, schema_editor): """Reverse migration - reset all ordering to 0.""" Book = apps.get_model("myapp", "Book") Book.objects.all().update(my_order=0) class Migration(migrations.Migration): dependencies = [ ('myapp', '0001_initial'), ] operations = [ migrations.AddField( model_name='book', name='my_order', field=models.PositiveIntegerField(default=0, db_index=True), ), migrations.RunPython(reorder, reverse_code=reverse_reorder), ] ``` -------------------------------- ### Execute Reorder Management Command Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use the reorder command to initialize or repair ordering values for existing database records. ```bash # Reorder a single model python manage.py reorder myapp.Book # Reorder multiple models python manage.py reorder myapp.Book myapp.Chapter # Expected output: # Successfully reordered model "myapp.Book" # Successfully reordered model "myapp.Chapter" ``` -------------------------------- ### Create Data Migration for Ordering Fields Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Manually define a data migration to initialize ordering values when adding a new ordering field to an existing model. ```bash shell> ./manage.py makemigrations myapp ``` ```python 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']) ``` ```python class Migration(migrations.Migration): operations = [ .... migrations.RunPython(reorder, reverse_code=migrations.RunPython.noop), ] ``` ```bash shell> ./manage.py migrate myapp ``` -------------------------------- ### Create a sortable Tabular Inline admin Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Use `SortableTabularInline` to create a sortable tabular inline admin interface. This is an alternative to `SortableStackedInline`. ```python from django.contrib import admin from adminsortable2.admin import SortableTabularInline, SortableAdminMixin from myapp.models import Chapter class ChapterTabularInline(SortableTabularInline): model = Chapter @admin.register(SortableBook) class SortableBookAdmin(SortableAdminMixin, admin.ModelAdmin): ... inlines = [ChapterTabularInline] ``` -------------------------------- ### Custom Ordering with Reverse Sort Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Configure models and admins for descending order (newest first) by setting the 'ordering' attribute in both Meta class and the admin class. ```python # models.py from django.db import models class NewsArticle(models.Model): title = models.CharField(max_length=255) my_order = models.PositiveIntegerField(default=0, db_index=True) class Meta: ordering = ['-my_order'] ``` ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminMixin from myapp.models import NewsArticle @admin.register(NewsArticle) class NewsArticleAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'my_order'] ordering = ['-my_order'] ``` -------------------------------- ### Configure Inheritance with Django-Solo Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Ensure SortableAdminBase is inherited before SingletonModelAdmin to avoid TypeErrors during admin save operations. ```python @admin.register(models.Homepage) class HomepageAdmin(SingletonModelAdmin, SortableAdminBase): # ... ``` ```python @admin.register(models.Homepage) class HomepageAdmin(SortableAdminBase, SingletonModelAdmin): # ... ``` -------------------------------- ### Configure Sortable Tabular Inlines Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Use SortableInlineAdminMixin and SortableAdminBase to enable drag-and-drop sorting for inlines in the Django admin. ```python from django.contrib import admin from adminsortable2.admin import SortableInlineAdminMixin, SortableAdminBase from models import Panel class ButtonTabularInline(SortableInlineAdminMixin, admin.TabularInline): # We don't use the Button model but rather the juction model specified on Panel. model = Panel.buttons.through @admin.register(Panel) class PanelAdmin(SortableAdminBase, admin.ModelAdmin): inlines = (ButtonTabularInline,) ``` -------------------------------- ### Create a Sortable Model Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Define a model with a numeric ordering field (e.g., PositiveIntegerField) and specify it in the Meta.ordering attribute. The ordering field should be the first in the list. ```python # models.py from django.db import models class Book(models.Model): title = models.CharField( "Title", max_length=255, ) author = models.CharField( "Author", max_length=255, blank=True, ) my_order = models.PositiveIntegerField( default=0, blank=False, null=False, db_index=True, # Recommended for performance ) class Meta: ordering = ['my_order'] # Required: ordering field must be first def __str__(self): return self.title ``` -------------------------------- ### Implement Custom Inline Sorting Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use SortableInlineAdminMixin to specify custom ordering fields for inline models. ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin from myapp.models import Book, Chapter class ChapterInlineAscending(SortableInlineAdminMixin, admin.StackedInline): model = Chapter extra = 1 ordering = ['my_order'] # Ascending order class ChapterInlineDescending(SortableInlineAdminMixin, admin.StackedInline): model = Chapter extra = 1 ordering = ['-my_order'] # Descending order @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] ordering = ['my_order'] inlines = [ChapterInlineAscending] ``` -------------------------------- ### Create a sortable Stacked Inline admin Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Use `SortableStackedInline` to make a model's inline admin interface sortable. This requires importing the mixin and assigning it to the `inlines` in the parent admin. ```python from django.contrib import admin from adminsortable2.admin import SortableStackedInline, SortableAdminMixin from myapp.models import Chapter class ChapterStackedInline(SortableStackedInline): model = Chapter extra = 1 @admin.register(SortableBook) class SortableBookAdmin(SortableAdminMixin, admin.ModelAdmin): ... inlines = [ChapterStackedInline] ``` -------------------------------- ### Correct Inheritance Order for Admin Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Ensure SortableAdminBase is inherited before SingletonModelAdmin to prevent TypeErrors when combining with other admin classes. ```python from django.contrib import admin from solo.admin import SingletonModelAdmin from adminsortable2.admin import SortableAdminBase, SortableStackedInline from myapp.models import Homepage, HomepageSlide class HomepageSlideInline(SortableStackedInline): model = HomepageSlide extra = 1 @admin.register(Homepage) class HomepageAdmin(SortableAdminBase, SingletonModelAdmin): inlines = [HomepageSlideInline] ``` -------------------------------- ### Define a sortable Chapter model Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Define a model with an ordering field for sortable inlines. Ensure the model has an ordering field and is configured with `Meta.ordering`. ```python from django.db import models class Chapter(models.Model): book = models.ForeignKey( SortableBook, on_delete=models.CASCADE, related_name='chapters', ) title = models.CharField( "Title", max_length=255, ) my_order = models.PositiveIntegerField( default=0, blank=False, null=False, ) class Meta: ordering = ['my_order'] ``` -------------------------------- ### Configure Sortable Stacked Inlines Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use SortableStackedInline to enable drag-and-drop sorting for related models within a parent model's admin page. ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminBase, SortableStackedInline from myapp.models import Book, Chapter class ChapterStackedInline(SortableStackedInline): model = Chapter extra = 1 @admin.register(Book) class UnsortedBookAdmin(SortableAdminBase, admin.ModelAdmin): """Book list is NOT sortable, but Chapter inlines ARE sortable.""" list_display = ['title', 'author'] inlines = [ChapterStackedInline] ``` -------------------------------- ### Custom Max Order Logic with get_max_order Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Override get_max_order to customize how the maximum order value is calculated for new items, ensuring they are added to the end of their specific category's list. ```python from django.contrib import admin from django.db.models import Max from django.db.models.functions import Coalesce from adminsortable2.admin import SortableAdminMixin from myapp.models import Book @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'category', 'my_order'] def get_max_order(self, request, obj=None): """ New books are added at the end of their category's list, not the global list. """ if obj and obj.category: return self.model.objects.filter( category=obj.category ).aggregate( max_order=Coalesce(Max('my_order'), 0) )['max_order'] return super().get_max_order(request, obj) ``` -------------------------------- ### Sortable List View with SortableAdminMixin Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Combine SortableAdminMixin with admin.ModelAdmin to enable drag-and-drop sorting in the Django Admin list view. The 'my_order' field in list_display will show the drag handle. ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminMixin from myapp.models import Book @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] # my_order shows drag handle list_per_page = 20 # Alternative: Specify ordering in admin class instead of model Meta @admin.register(Book) class BookAdminWithOrdering(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] ordering = ['my_order'] # Can override model's Meta.ordering ``` -------------------------------- ### Sortable Tabular Inline with SortableTabularInline Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use SortableTabularInline for a compact, sortable tabular inline interface. Similar to Stacked Inlines, the parent admin needs to inherit from SortableAdminMixin or SortableAdminBase. ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminMixin, SortableTabularInline from myapp.models import Book, Chapter class ChapterTabularInline(SortableTabularInline): model = Chapter extra = 1 @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] inlines = [ChapterTabularInline] ``` -------------------------------- ### Sortable Stacked Inline with SortableStackedInline Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use SortableStackedInline to create sortable stacked inlines for related models. The parent admin must inherit from SortableAdminMixin or SortableAdminBase. ```python # models.py from django.db import models class Chapter(models.Model): book = models.ForeignKey( 'Book', on_delete=models.CASCADE, related_name='chapters', ) title = models.CharField("Title", max_length=255) my_order = models.PositiveIntegerField( default=0, blank=False, null=False, db_index=True, ) class Meta: ordering = ['my_order'] def __str__(self): return self.title # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminMixin, SortableStackedInline from myapp.models import Book, Chapter class ChapterStackedInline(SortableStackedInline): model = Chapter extra = 1 @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] inlines = [ChapterStackedInline] ``` -------------------------------- ### Register Model with SortableAdminMixin Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Register your sortable model with Django's admin using the SortableAdminMixin. This enables drag-and-drop sorting in the admin list view without further configuration. ```python from django.contrib import admin from adminsortable2.admin import SortableAdminMixin from myapp.models import SortableBook @admin.register(SortableBook) class SortableBookAdmin(SortableAdminMixin, admin.ModelAdmin): pass ``` -------------------------------- ### Unsorted Parent with Sorted Inlines using SortableAdminBase Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Use SortableAdminBase for the parent model admin when only the inlines need to be sortable, not the parent's list view. This mixin provides necessary JS/CSS for sortable inlines. ```python # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminBase, SortableStackedInline from myapp.models import Book, Chapter class ChapterStackedInline(SortableStackedInline): model = Chapter extra = 1 @admin.register(Book) class BookAdmin(SortableAdminBase, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] inlines = [ChapterStackedInline] ``` -------------------------------- ### Customize List Display with Ordering Field Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md To control the columns displayed in the admin list view and position the draggable area, define the `list_display` attribute in your ModelAdmin. The ordering field should be included in this list. ```python @admin.register(SortableBook) class SortableBookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'my_order'] ``` -------------------------------- ### Extend Django Admin Change List Template Source: https://github.com/jrief/django-admin-sortable2/blob/master/adminsortable2/templates/adminsortable2/change_list.html Use this template block to inject the update URL and pagination metadata into the admin change list page. ```html {% extends base_change_list_template|default:'admin/change_list.html' %} {% block extrahead %} {{ block.super }} { "update_url": "{{ sortable_update_url }}", "current_page": {{ cl.page_num }}, "total_pages": {{ cl.paginator.num_pages }} } {% endblock %} ``` -------------------------------- ### Sort Many-to-Many Relationships Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Enable sorting for M2M relations by defining a through model with an explicit ordering field. ```python # models.py from django.db import models class Button(models.Model): name = models.CharField(max_length=64) button_text = models.CharField(max_length=64) def __str__(self): return self.name class Panel(models.Model): name = models.CharField(max_length=64) buttons = models.ManyToManyField(Button, through='PanelButtons') def __str__(self): return self.name class PanelButtons(models.Model): """Junction table with ordering field for sortable M2M.""" panel = models.ForeignKey(Panel, on_delete=models.CASCADE) button = models.ForeignKey(Button, on_delete=models.CASCADE) button_order = models.PositiveIntegerField(default=0) class Meta: ordering = ['button_order'] # admin.py from django.contrib import admin from adminsortable2.admin import SortableAdminBase, SortableInlineAdminMixin from myapp.models import Panel, Button class ButtonTabularInline(SortableInlineAdminMixin, admin.TabularInline): model = Panel.buttons.through # Use the through model @admin.register(Panel) class PanelAdmin(SortableAdminBase, admin.ModelAdmin): list_display = ['name'] inlines = [ButtonTabularInline] @admin.register(Button) class ButtonAdmin(admin.ModelAdmin): list_display = ['name', 'button_text'] ``` -------------------------------- ### Define a Sortable Model Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Define a Django model with a field for ordering. Ensure the ordering field is a positive integer, has a default of 0, is indexed, and is editable. The ordering field must be the first in the model's Meta class ordering. ```python from django.db import models class SortableBook(models.Model): title = models.CharField( "Title", max_length=255, ) my_order = models.PositiveIntegerField( default=0, blank=False, null=False, ) class Meta: ordering = ['my_order'] ``` -------------------------------- ### Specify Ordering Field in ModelAdmin Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md If the model does not specify a default ordering field in its Meta class, you can define it within the ModelAdmin class. This ensures the admin interface uses the correct field for sorting. ```python @admin.register(SortableBook) class SortableBookAdmin(SortableAdminMixin, admin.ModelAdmin): ordering = ['my_order'] ``` -------------------------------- ### Filtered Sorting with get_extra_model_filters Source: https://context7.com/jrief/django-admin-sortable2/llms.txt Override get_extra_model_filters to restrict sorting to specific subsets of objects, such as items within the same category. This method returns additional filter kwargs for the sortable queryset. ```python from django.contrib import admin from adminsortable2.admin import SortableAdminMixin from myapp.models import Book @admin.register(Book) class BookAdmin(SortableAdminMixin, admin.ModelAdmin): list_display = ['title', 'author', 'category', 'my_order'] list_filter = ['category'] @staticmethod def get_extra_model_filters(request): """ Filter sorting to only affect items in the same category. Returns additional filter kwargs for the sortable queryset. """ category = request.GET.get('category__exact') if category: return {'category': category} return {} ``` -------------------------------- ### Define junction model for sortable Many-to-Many Source: https://github.com/jrief/django-admin-sortable2/blob/master/docs/source/usage.md Define a junction model with an ordering field to manage sortable Many-to-Many relations. This model is specified using the `through` parameter in `models.ManyToManyField`. ```python from django.db import models class Button(models.Model): """A button""" name = models.CharField(max_length=64) button_text = models.CharField(max_length=64) class Panel(models.Model): """A Panel of Buttons - this represents a control panel.""" name = models.CharField(max_length=64) buttons = models.ManyToManyField(Button, through='PanelButtons') class PanelButtons(models.Model): """This is a junction table model that also stores the button order for a panel.""" panel = models.ForeignKey(Panel) button = models.ForeignKey(Button) button_order = models.PositiveIntegerField(default=0) class Meta: ordering = ['button_order'] ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.