An improved version of http://djangosnippets.org/snippets/1016/ which lets you add separate buttons for change_list and change_form pages in the admin.
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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | class ButtonAdmin(admin.ModelAdmin):
"""
A subclass of this admin will let you add buttons (like history) in the
change view of an entry.
ex.
class FooAdmin(ButtonAdmin):
...
def bar(self, request, obj=None):
if obj != None: obj.bar()
return None # Redirect or Response or None
bar.short_description='Example button'
list_buttons = [ bar ]
change_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 %}
"""
change_buttons=[]
list_buttons=[]
def button_view_dispatcher(self, request, url):
# Dispatch the url to a function call
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.change_buttons]:
obj = self.model._default_manager.get(pk=res.group('id'))
response = getattr(self, res.group('command'))(request, obj)
if response is None:
from django.http import HttpResponseRedirect
return HttpResponseRedirect(request.META['HTTP_REFERER'])
return response
else:
res = re.match('(.*/)?(?P<command>.*)', url)
if res:
if res.group('command') in [b.func_name for b in self.list_buttons]:
response = getattr(self, res.group('command'))(request)
if response is None:
from django.http import HttpResponseRedirect
return HttpResponseRedirect(request.META['HTTP_REFERER'])
return response
# Delegate to the appropriate method, based on the URL.
from django.contrib.admin.util import unquote
if url is None:
return self.changelist_view(request)
elif url == "add":
return self.add_view(request)
elif url.endswith('/history'):
return self.history_view(request, unquote(url[:-8]))
elif url.endswith('/delete'):
return self.delete_view(request, unquote(url[:-7]))
else:
return self.change_view(request, unquote(url))
def get_urls(self):
from django.conf.urls.defaults import url, patterns
from django.utils.functional import update_wrapper
# Define a wrapper view
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)
# Add the custom button url
urlpatterns = patterns('',
url(r'^(.+)/$', wrap(self.button_view_dispatcher),)
)
return urlpatterns + super(ButtonAdmin, self).get_urls()
def change_view(self, request, object_id, form_url='', extra_context=None):
if not extra_context: extra_context = {}
if hasattr(self, 'change_buttons'):
extra_context['buttons'] = self._convert_buttons(self.change_buttons)
if '/' in object_id:
object_id = object_id[:object_id.find('/')]
return super(ButtonAdmin, self).change_view(request, object_id, form_url, extra_context)
def changelist_view(self, request, extra_context=None):
if not extra_context: extra_context = {}
if hasattr(self, 'list_buttons'):
extra_context['buttons'] = self._convert_buttons(self.list_buttons)
return super(ButtonAdmin, self).changelist_view(request, extra_context)
def _convert_buttons(self, orig_buttons):
buttons = []
for b in orig_buttons:
buttons.append({ 'func_name': b.func_name, 'short_description': b.short_description })
return buttons
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
to use this snippet in django 1.4, modify change_view signature like below <br /> def change_view(self, request, object_id, form_url='', extra_context=None): .... <br /> return super(ButtonAdmin, self).change_view(request, object_id, form_url, extra_context)
#
Done thanx !
#
from django.conf.urls.defaults is deprecated, use rather from django.conf.urls
Else, really nice snippet ! Congrats !
#
Please login first before commenting.