labs/tabbed_admin/admin.py

155 lines
6.2 KiB
Python

from django.conf import settings
from django.contrib.admin.options import ModelAdmin
from django.utils.translation import gettext_lazy as _
from .settings import USE_JQUERY_UI, JQUERY_UI_CSS, JQUERY_UI_JS
class TabbedModelAdmin(ModelAdmin):
tabs = None
formatted_tabs = {}
# Needs a specific template to display the tabs
change_form_template = 'tabbed_admin/change_form.html'
def get_fieldsets(self, request, obj=None):
"""
Overwrites BaseModelAdmin fieldsets to add fieldsets passed by the
tabs.
If the tabs attribute is not set, use the default ModelAdmin method.
"""
tabs_fieldsets = self.get_formatted_tabs(request, obj)['fieldsets']
if self.tabs is not None:
self.fieldsets = ()
self.fieldsets = self.add_tabbed_item(tabs_fieldsets, self.fieldsets)
return super(TabbedModelAdmin, self).get_fieldsets(request, obj)
def get_inline_instances(self, request, obj=None):
"""
Overwrites BaseModelAdmin fieldsets to add fieldsets passed by the
tabs.
If the tabs attribute is not set, use the default ModelAdmin method.
"""
if self.tabs is not None:
self.inlines = ()
tabs_inlines = self.get_formatted_tabs(request, obj)['inlines']
self.inlines = self.add_tabbed_item(tabs_inlines, self.inlines)
try:
# django >=1.7
return super(TabbedModelAdmin, self)\
.get_inline_instances(request, obj)
except TypeError:
return super(TabbedModelAdmin, self).get_inline_instances(request)
def add_tabbed_item(self, items_to_add, collection):
"""
Adds tabbed items (inlines or fieldsets) to their corresponding
attribute.
"""
if items_to_add:
for item in items_to_add:
if item not in collection:
if type(collection) == tuple:
collection = collection + (item, )
elif type(collection) == list:
collection.append(item)
return collection
def get_tabs(self, request, obj=None):
"""
Returns the tabs attribute.
"""
return self.tabs
def get_formatted_tabs(self, request, obj=None):
"""
Returns the formated tabs attribute.
"""
if self.tabs:
self.parse_fieldsets_inlines_from_tabs(request, obj)
return self.formatted_tabs
def parse_fieldsets_inlines_from_tabs(self, request, obj=None):
"""
Parses the self.tabs attribute. Checks its integrity and populates
self._tabs_fieldsets and self._tabs_inlines attributes.
"""
tabs_fieldsets = ()
tabs_inlines = ()
self.formatted_tabs['fields'] = []
for tab in self.get_tabs(request, obj):
# Checks that each tab if formated with 2 arguments, verbose name
# of the tab and the tab configuration.
if type(tab) not in [tuple, list]:
raise TypeError(
_(u'Each tab entry must be either a list or a tuple'))
if len(tab) != 2:
raise ValueError(
_(u'Each tabs entry must contain 2 arguments: a verbose name and the tab setup.'))
if type(tab[1]) not in [tuple, list]:
raise TypeError(
_(u'A tab definition must be either a list or a tuple'))
# So far all went well, lets parse the tab configuration, we go
# through each item. If its a tuple or a list we consider its a
# fieldset, otherwise its a tuple.
formatted_tab = {'name': tab[0], 'entries': []}
for tab_entry in tab[1]:
formatted_tab_entry = {}
if type(tab_entry) in [tuple, list]:
tabs_fieldsets = tabs_fieldsets + (tab_entry, )
formatted_tab_entry = {'type': 'fieldset',
'name': tab_entry[0],
'config': tab_entry[1]}
else:
tabs_inlines = tabs_inlines + (tab_entry, )
formatted_tab_entry = {'type': 'inline',
'name': tab_entry.__name__}
formatted_tab['entries'].append(formatted_tab_entry)
self.formatted_tabs['fields'].append(formatted_tab)
self.formatted_tabs['fieldsets'] = tabs_fieldsets
self.formatted_tabs['inlines'] = tabs_inlines
def add_view(self, request, form_url='', extra_context=None):
"""
Overwrites add_view to insert the tabs config for the template.
"""
if extra_context is None:
extra_context = {}
extra_context.update({'tabs': self.get_formatted_tabs(request)})
return super(TabbedModelAdmin, self)\
.add_view(request, form_url=form_url, extra_context=extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None):
"""
Overwrites change_view to insert the tabs config for the template.
"""
try:
# django 1.4
change_view = super(TabbedModelAdmin, self)\
.change_view(request, object_id, form_url=form_url,
extra_context=extra_context)
except TypeError:
# django 1.3
change_view = super(TabbedModelAdmin, self)\
.change_view(request, object_id, extra_context=extra_context)
if hasattr(change_view, 'context_data'):
change_view.context_data.update(
{'tabs': self.get_formatted_tabs(request,
change_view.context_data.get('original'))}
)
return change_view
class Media:
"""
Extends media class to add custom jquery ui if
TABBED_ADMIN_USE_JQUERY_UI is set to True.
"""
if 'grappelli' in settings.INSTALLED_APPS:
css = {'all': ("tabbed_admin/css/tabbed_grappelli_admin.css", )}
if USE_JQUERY_UI:
css = {
'all': (JQUERY_UI_CSS, 'tabbed_admin/css/tabbed_admin.css', )}
js = (JQUERY_UI_JS,)