Source code for superdjango.db.sorted.utils

"""
Sortation utilities are separated from the ``SortedModel`` in order to keep the model clean and prevent possible
collisions or conflicts with method names.

They may still be used in a declarative manner, for example:

.. code-block:: python

    from superdjango.db.sorted import utils as sortation
    from .models import Task

    task = Task.objects.get(pk=1234)

    if sortation.has_previous_record(task):
        previous_task = sortation.get_previous_record(task)

    if sortation.has_next_record(task):
        next_task = sortation.get_next_record(task)

"""

# Exports

__all__ = (
    "get_next_record",
    "get_previous_record",
    "has_next_record",
    "has_previous_record",
    "is_sortable",
)

# Functions


[docs]def get_previous_record(instance, **criteria): """Get the previous record, if one exists. :param instance: The instance to be checked. :param criteria: Additional criteria to be given. This is useful when the record is embedded in a hierarchy. :type criteria: dict :rtype: models.Model :returns: Returns the previous instance or ``None`` if a previous instance could not be found. """ if not is_sortable(instance): return None cls = instance.__class__ fn = "sort_order" try: criteria['%s__lt' % fn] = instance.sort_order return cls.objects.filter(**criteria).order_by("-%s" % fn)[0] except IndexError: return None
[docs]def get_next_record(instance, **criteria): """Get the next record, if one exists. :param instance: The instance to be checked. :param criteria: Additional criteria to be given. This is useful when the record is embedded in a hierarchy. :type criteria: dict :rtype: models.Model :returns: Returns the next instance or ``None`` if a next instance could not be found. """ if not is_sortable(instance): return None cls = instance.__class__ fn = "sort_order" try: criteria['%s__gt' % fn] = instance.sort_order return cls.objects.filter(**criteria).order_by("-%s" % fn)[0] except IndexError: return None
[docs]def has_next_record(instance, **criteria): """Indicates whether a record exists with a higher sort order. :param instance: The instance to be checked. :param criteria: Additional criteria to be given. This is useful when the record is embedded in a hierarchy. :type criteria: dict :rtype: bool """ cls = instance.__class__ fn = "sort_order" criteria['%s__gt' % fn] = instance.sort_order return cls.objects.filter(**criteria).count() > 0
[docs]def has_previous_record(instance, **criteria): """Indicates whether a record exists with a lower sort order. :param instance: The instance to be checked. :param criteria: Additional criteria to be given. This is useful when the record is embedded in a hierarchy. :type criteria: dict :rtype: bool """ cls = instance.__class__ fn = "sort_order" criteria['%s__lt' % fn] = instance.sort_order return cls.objects.filter(**criteria).count() > 0
[docs]def is_sortable(instance): """Determine whether a given instance is sortable. :param instance: The instance to be checked. :type instance: object :rtype: bool :returns: Returns ``True`` if the instance inherits from :py:class:`SortedModel` *or* a ``sort_order`` attribute is defined on the instance. """ # Avoid import errors. from .models import SortedModel if isinstance(instance, SortedModel): return True elif hasattr(instance, "sort_order"): return True else: return False