Login

DRY custom ModelAdmin.list_display methods with a decorator

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

If you add a lot of custom ModelAdmin methods to list_display like I do, you know it can require a lot of repetition. Notice how adding 'checkbox' to list_display requires typing the method name 4 times:

class ExampleAdmin(admin.ModelAdmin):
    list_display = ['checkbox', '__str__']

    def checkbox(self, object):
        return '<input type="checkbox" value="%s"/>' % object.pk
    checkbox.short_description = mark_safe('&#x2713;')
    checkbox.allow_tags = True

Using this decorator, the name only needs to be typed once:

class ExampleAdmin(admin.ModelAdmin):
    list_display = ['__str__']

    @add(list_display, mark_safe('&#x2713;'), 0, allow_tags=True)
    def checkbox(self, object):
        return '<input type="checkbox" value="%s"/>' % object.pk
 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
37
def add(list_, short_description=None, position=None, **kwargs):
    """
    A helper to add a method to `list_` (usually `ModelAdmin.list_display`),
    where the method's name is added, and items may have attributes like
    `short_description` and `boolean`.
    
    `position` is the index at which to insert the item. By default, items
    are appended.
    
    Example:
    
    class ExampleAdmin(admin.ModelAdmin):
        list_display = ['__str__']
        
        @add(list_display, "in progress?", boolean=True)
        def in_progress(self, object):
            return not object.is_complete
    
        @add(list_display, mark_safe('&#x2713;'), 0, allow_tags=True)
        def checkbox(self, object):
            return '<input type="checkbox" value="%s"/>' % object.pk
    
    """
    if short_description is not None:
        kwargs['short_description'] = short_description
    def decorate(f):
        if isinstance(f, basestring):
            list_.append(f)
        else:
            for key, value in kwargs.iteritems():
                setattr(f, key, value)
            if position is None:
                list_.append(f.__name__)
            else:
                list_.insert(position, f.__name__)
            return f
    return decorate

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, 7 months ago

Comments

Please login first before commenting.