Source code for superdjango.db.sorted.models

# Imports

from django.conf import settings
from django.db import models
from django.db.models import F
from django.utils.translation import ugettext_lazy as _

# Exports

__all__ = (
    "SortedModel",
)

# Constants

AUTH_USER_MODEL = settings.AUTH_USER_MODEL

# Models


[docs]class SortedModel(models.Model): """Allow a model to be easily sortable. **Fields** - ``sort_order`` **Implementation** .. code-block:: python from superdjango.db.sorted.models import SortedModel class Task(SortedModel): # ... class Meta: ordering = ["sort_order"] """ sort_order = models.IntegerField( _("sort order"), default=1, help_text=_("How the record should be sorted.") ) class Meta: abstract = True # noinspection PyUnusedLocal
[docs] @staticmethod def pre_save_sort_order(sender, instance, **kwargs): """Insure that the ``sort_order`` has a value. .. code-block:: python from django.db.models.signals import pre_save from .models import Task pre_save.connect( Task.pre_save_sort_order, Task, dispatch_uid="task_pre_save_sort_order" ) """ if not instance.sort_order or instance.sort_order == 0: try: # Get the previous sort order. last = sender.objects.values("sort_order").order_by('-%s' % "sort_order")[0] instance.sort_order = last["sort_order"] + 1 except IndexError: # Set the sort order to 1 if this is the first record. instance.sort_order = 1
[docs] def update_sort_order(self, sort_order, commit=True): """Move the record to a different position, shifting the other records around it. :param sort_order: The new position. :type sort_order: int :param commit: Indicates whether to save the record after the move. :type commit: bool """ # Force the new position to be an integer. This ensures the method works when interacting with a web-based API. new_position = int(sort_order) # The default position is always 1. original_position = self.sort_order # There's nothing to do if the new position isn't actually different. if new_position == original_position: return # Prepare to move other records out of the way. # noinspection PyTypeChecker if new_position < original_position: shift_amount = 1 # noinspection PyTypeChecker select_range = (new_position, original_position - 1) else: shift_amount = -1 # noinspection PyTypeChecker select_range = (original_position + 1, new_position) # Shorten the statements by getting the class here. cls = self.__class__ # Update records. criteria = { 'sort_order__range': select_range, } # noinspection PyUnresolvedReferences qs = cls.objects.filter(**criteria) for row in qs: row.update(field=F("sort_order") + shift_amount) # Save the new position. self.sort_order = new_position if commit: # noinspection PyUnresolvedReferences self.save()