class SortableModel(models.Model):
"""
Abstract model which makes an inherited model's records sortable
by calling instance.move(position)
"""
order = models.IntegerField(default=0)
class Meta:
abstract = True
ordering = ['order']
@staticmethod
def pre_save(sender, instance, **kwargs):
"""
makes sure we have a value for order. This must be connected to the
pre_save event for the inheriting model.
"""
if not instance.order or instance.order == 0:
#get last order
try:
last = sender.objects.values('order').order_by('-order')[0]
instance.order = last['order'] + 1
except IndexError:
instance.order = 1
def move(self, to):
to = int(to)
orig = self.order
if to == orig:
return
# make sure initial ordering is "clean". Not ideal, but sometimes needed
for i, f in enumerate(ReportField.objects.all()):
f.order = i+1
f.save()
# make some room
shift, range = to < orig and (1, (to, orig-1)) or (-1, (orig+1, to))
ReportField.objects.filter(order__range=range).update(order=F('order')+shift)
# move it
self.order = to
self.save()
Comments