sortable — Making objects sortable

To make a model sortable, you need the following two additions to your model:

  1. You need to inherit from SortableBase (an abstract model) instead of django.db.Model,
  2. You need to create a subclass of SortableItemQuerySet and attach that subclass as a queryset for your model.

Example:

from django_cradmin.sortable.models import SortableBase
from django_cradmin.sortable.models import SortableQuerySetBase

class MySortableItemQuerySet(SortableQuerySetBase):
    parent_attribute = 'container'

class MySortableItem(SortableBase):
    objects = MySortableItemQuerySet.as_manager()
    container = models.ForeignKey(ItemContainer, blank=False, null=False)
    name = models.CharField(...)

The class that inherits SortableBase gets an attribute sort_index. If you want the default ordering for this model to be this attribute, you should add the following meta option on the model:

class Meta:
    ordering = ['sort_index']

How to sort

Sorting is done by using these methods:

Example:

# Make a new item and put it last in the list
myitem = MySortableItem(container=somecontainer, name='Some name')
MySortableItem.objects.set_newitem_sort_index_to_last(myitem)
myitem.save()

# Move the given item before the item with id 777
# NOTE: Unlike set_newitem_sort_index_to_last(), sort_before() and sort_last()
#       saves the item.
MySortableItem.objects.sort_before(someitem, sort_before_id=777)

# Move the given item last in the list
MySortableItem.objects.sort_last(someitem)
# ... or ...
MySortableItem.objects.sort_before(someitem, sort_before_id=None)

Makin an Admin UI that automatically adds items last in parent

Making an Admin UI that automatically adds items last in parent is easy. Just extend django_cradmin.sortable.admin.SortableModelAdmin instead of django.contrib.admin.ModelAdmin:

from django_cradmin.sortable.admin import SortableModelAdmin

class MySortableItemAdmin(SortableModelAdmin):
    pass

admin.site.register(models.MySortableItem, MySortableItemAdmin)

You may also want to show the sort order by default in the admin UI listing, with something like this:

class MySortableItemAdmin(SortableModelAdmin):
    ordering = ['container__name', 'sort_index']

API

class SortableQuerySetBase(model=None, query=None, using=None, hints=None)

Bases: django_cradmin.utils.nulls_last_queryset.NullsLastQuerySet

QuerySet for SortableManagerBase.

You must use this as a base class if you want to create a custom queryset class for models extending SortableBase.

set_newitem_sort_index_to_last(item, none_values_order_by=None)

Sets item.sort_index to the sort_index of the last item in the parent + 1. Does not save.

ONLY USE THIS FOR NEWLY CREATED ITEMS.

sort_before(item, sort_before_id, none_values_order_by=None)

Sort a given item before the item with id sort_before_id, or last if sort_before_id is None.

Fetches all items in the same container, and makes changes in the ordering. Only the required updates are made.

sort_last(item, none_values_order_by=None)

Just a shortcut for:

self.sort_before(item, sort_before_id=None)
class SortableBase(*args, **kwargs)

Bases: django.db.models.base.Model

Used with SortableQuerySetBase to make models sortable.

sort_index

Sort index - 0 or higher.

class SortableModelAdmin(model, admin_site)

Bases: django.contrib.admin.options.ModelAdmin

ModelAdmin that automatically sets the sort_index of newly added items last in their parent. It also makes sort_index read-only by default.

Used just like django.contrib.admin.ModelAdmin.

make_sort_index_readonly = False

If this is True , we make the sort_index field read-only. Override this to avoid this magic (typically for debugging).

save_model(request, obj, form, change)

Overridden to set the sortindex on save if the pk is None.

get_readonly_fields(request, obj=None)

Overridden to make the sortindex readonly if make_sort_index_readonly is True.