Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2Sortation utilities are separated from the ``SortedModel`` in order to keep the model clean and prevent possible 

3collisions or conflicts with method names. 

4 

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

6 

7.. code-block:: python 

8 

9 from superdjango.db.sorted import utils as sortation 

10 from .models import Task 

11 

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

13 

14 if sortation.has_previous_record(task): 

15 previous_task = sortation.get_previous_record(task) 

16 

17 if sortation.has_next_record(task): 

18 next_task = sortation.get_next_record(task) 

19 

20""" 

21 

22# Exports 

23 

24__all__ = ( 

25 "get_next_record", 

26 "get_previous_record", 

27 "has_next_record", 

28 "has_previous_record", 

29 "is_sortable", 

30) 

31 

32# Functions 

33 

34 

35def get_previous_record(instance, **criteria): 

36 """Get the previous record, if one exists. 

37 

38 :param instance: The instance to be checked. 

39 

40 :param criteria: Additional criteria to be given. This is useful when 

41 the record is embedded in a hierarchy. 

42 :type criteria: dict 

43 

44 :rtype: models.Model 

45 :returns: Returns the previous instance or ``None`` if a previous instance 

46 could not be found. 

47 

48 """ 

49 if not is_sortable(instance): 

50 return None 

51 

52 cls = instance.__class__ 

53 

54 fn = "sort_order" 

55 try: 

56 criteria['%s__lt' % fn] = instance.sort_order 

57 return cls.objects.filter(**criteria).order_by("-%s" % fn)[0] 

58 except IndexError: 

59 return None 

60 

61 

62def get_next_record(instance, **criteria): 

63 """Get the next record, if one exists. 

64 

65 :param instance: The instance to be checked. 

66 

67 :param criteria: Additional criteria to be given. This is useful when 

68 the record is embedded in a hierarchy. 

69 :type criteria: dict 

70 

71 :rtype: models.Model 

72 :returns: Returns the next instance or ``None`` if a next instance 

73 could not be found. 

74 

75 """ 

76 if not is_sortable(instance): 

77 return None 

78 

79 cls = instance.__class__ 

80 

81 fn = "sort_order" 

82 try: 

83 criteria['%s__gt' % fn] = instance.sort_order 

84 return cls.objects.filter(**criteria).order_by("-%s" % fn)[0] 

85 except IndexError: 

86 return None 

87 

88 

89def has_next_record(instance, **criteria): 

90 """Indicates whether a record exists with a higher sort order. 

91 

92 :param instance: The instance to be checked. 

93 

94 :param criteria: Additional criteria to be given. This is useful when 

95 the record is embedded in a hierarchy. 

96 :type criteria: dict 

97 

98 :rtype: bool 

99 

100 """ 

101 cls = instance.__class__ 

102 fn = "sort_order" 

103 

104 criteria['%s__gt' % fn] = instance.sort_order 

105 return cls.objects.filter(**criteria).count() > 0 

106 

107 

108def has_previous_record(instance, **criteria): 

109 """Indicates whether a record exists with a lower sort order. 

110 

111 :param instance: The instance to be checked. 

112 

113 :param criteria: Additional criteria to be given. This is useful when 

114 the record is embedded in a hierarchy. 

115 :type criteria: dict 

116 

117 :rtype: bool 

118 

119 """ 

120 cls = instance.__class__ 

121 fn = "sort_order" 

122 

123 criteria['%s__lt' % fn] = instance.sort_order 

124 return cls.objects.filter(**criteria).count() > 0 

125 

126 

127def is_sortable(instance): 

128 """Determine whether a given instance is sortable. 

129 

130 :param instance: The instance to be checked. 

131 :type instance: object 

132 

133 :rtype: bool 

134 :returns: Returns ``True`` if the instance inherits from :py:class:`SortedModel` *or* a ``sort_order`` attribute is 

135 defined on the instance. 

136 

137 """ 

138 # Avoid import errors. 

139 from .models import SortedModel 

140 

141 if isinstance(instance, SortedModel): 

142 return True 

143 elif hasattr(instance, "sort_order"): 

144 return True 

145 else: 

146 return False