155 lines
6.2 KiB
Python
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,)
|