Login

Moving items up/down from the admin interface

Author:
vicox
Posted:
September 5, 2008
Language:
Python
Version:
1.0
Score:
4 (after 4 ratings)

Move Items up and down from the admin interface. Like phpBB does it with its forums.

An additional select field is added to the admin form. After the model has been saved, a model method is called (with the value of the new field), which handles the reordering.

A more detailed description and a screenshot can be found here.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MyModel(models.Model):
	order = models.IntegerField(editable=False)
	#...

	def move(self, move):
		if move == 'UP':
			mm = MyModel.objects.get(order=self.order-1)
			mm.order += 1
			mm.save()
			self.order -= 1
			self.save()
			#...

class MyModelAdminForm(forms.ModelForm):
	move = forms.CharField(widget=forms.Select)
	move.required = False
	move.widget.choices=(
			(models.BLANK_CHOICE_DASH[0]),
			('FIRST', 'First'),
			('UP', 'Up'),
			('DOWN', 'Down'),
			('LAST', 'Last'),
		)
 
	class Meta:
		model = MyModel

class MyModelAdmin(admin.ModelAdmin):
	form = MyModelAdminForm
 
	def save_model(self, request, obj, form, change):
		obj.save()
		move = form.cleaned_data['move']
		obj.move(move)

admin.site.register(MyModel, MyModelAdmin)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 8 months ago

Comments

erikcw (on April 16, 2009):

Here is the full "move()" model method. I added some smarts to the algorithm to prevent "skipping".

def save(self, force_insert=False, force_update=False):
    """Custom save to add order property (make last item)."""
    if not self.order: #if this is a new object.
        mm = MyModel.objects.all().latest('order')
        self.order = mm.order + 1
    super(MyModel, self).save(force_insert, force_update)

def move(self, move):
    """Change the ordering of an object."""
    if move == 'UP':
        try:
            mm = MyModel.objects.filter(order__lt=self.order).order_by('-order')[0]
            self.order = mm.order
            mm.order += 1
            mm.save()
            self.save()
        except IndexError:
            pass
    elif move == 'DOWN':
        try:
            mm = MyModel.objects.filter(order__gt=self.order).order_by('order')[0]
            self.order = mm.order
            mm.order -= 1
            mm.save()
            self.save()
        except IndexError:
            pass
    elif move == 'FIRST':
        mm = MyModel.objects.all().order_by('order')[0]
        self.order = mm.order - 1
        self.save()
    elif move == 'LAST':
        mm = MyModel.objects.all().order_by('-order')[0]
        self.order = mm.order + 1
        self.save()

#

Please login first before commenting.