Login

Add a button to the top of the admin change form

Author:
tsaylor
Posted:
February 23, 2010
Language:
Python
Version:
1.1
Score:
1 (after 1 ratings)

I found snippet #1016 while looking for a way to add a button to the top of an admin change form, and it didn't work. I found that it used the old admin, so I updated it to django 1.1.1

 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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class ButtonableModelAdmin(admin.ModelAdmin):
   """
   Django snippet # 1936
   Derived from django snippet # 1016
   http://www.djangosnippets.org/snippets/1936/

   A subclass of this admin will let you add buttons (like history) in the
   change view of an entry.

   ex.
   class FooAdmin(ButtonableModelAdmin):
      ...

      def bar(self, obj):
         obj.bar()
      bar.short_description='Example button'

      buttons = [ bar ]

   you can then put the following in your admin/change_form.html template:

      {% block object-tools %}
      {% if change %}{% if not is_popup %}
      <ul class="object-tools">
      {% for button in buttons %}
         <li><a href="{{ button.func_name }}/">{{ button.short_description }}</a></li>
      {% endfor %}
      <li><a href="history/" class="historylink">History</a></li>
      {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">View on site</a></li>{% endif%}
      </ul>
      {% endif %}{% endif %}
      {% endblock %}

   """
   buttons=[]

   def change_view(self, request, object_id, extra_context={}):
      extra_context['buttons']=self.buttons
      if '/' in object_id:
         object_id = object_id[:object_id.find('/')]
      return super(ButtonableModelAdmin, self).change_view(request, object_id, extra_context)

   def button_view_dispatcher(self, request, url):
      if url is not None:
         import re
         res=re.match('(.*/)?(?P<id>\d+)/(?P<command>.*)', url)
         if res:
            if res.group('command') in [b.func_name for b in self.buttons]:
               obj = self.model._default_manager.get(pk=res.group('id'))
               getattr(self, res.group('command'))(obj)
               return HttpResponseRedirect(request.META['HTTP_REFERER'])

      return super(ButtonableModelAdmin, self).__call__(request, url)

   def get_urls(self):
       from django.conf.urls.defaults import patterns, url

       def wrap(view):
           def wrapper(*args, **kwargs):
               return self.admin_site.admin_view(view)(*args, **kwargs)
           return update_wrapper(wrapper, view)

       urlpatterns = patterns('',
           url(r'^(.+)/$',
               wrap(self.button_view_dispatcher),)
       ) + super(ButtonableModelAdmin, self).get_urls()
       return urlpatterns

More like this

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

Comments

[email protected] (on March 3, 2011):

I have just tried using this snippet and recieve an error msg: global name 'update_srapper' is not defined. Would appreciate some assistance.

#

IzzaddinRuhulessin (on June 5, 2011):

Solution:

from django.utils.functional import update_wrapper

#

Please login first before commenting.