123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- import datetime
- import json
- from django.template import Context
- from django.utils import translation
- from jet import settings
- from jet.models import PinnedApplication
- try:
- from django.apps.registry import apps
- except ImportError:
- try:
- from django.apps import apps # Fix Django 1.7 import issue
- except ImportError:
- pass
- from django.core.serializers.json import DjangoJSONEncoder
- from django.http import HttpResponse
- try:
- from django.core.urlresolvers import reverse, resolve, NoReverseMatch
- except ImportError: # Django 1.11
- from django.urls import reverse, resolve, NoReverseMatch
- from django.contrib.admin import AdminSite
- from django.utils.encoding import smart_text
- from django.utils.text import capfirst
- from django.contrib import messages
- from django.utils.encoding import force_text
- from django.utils.functional import Promise
- from django.contrib.admin.options import IncorrectLookupParameters
- from django.contrib import admin
- from django.utils.translation import ugettext_lazy as _
- from django.utils.text import slugify
- try:
- from collections import OrderedDict
- except ImportError:
- from ordereddict import OrderedDict # Python 2.6
- class JsonResponse(HttpResponse):
- """
- An HTTP response class that consumes data to be serialized to JSON.
- :param data: Data to be dumped into json. By default only ``dict`` objects
- are allowed to be passed due to a security flaw before EcmaScript 5. See
- the ``safe`` parameter for more information.
- :param encoder: Should be an json encoder class. Defaults to
- ``django.core.serializers.json.DjangoJSONEncoder``.
- :param safe: Controls if only ``dict`` objects may be serialized. Defaults
- to ``True``.
- """
- def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs):
- if safe and not isinstance(data, dict):
- raise TypeError('In order to allow non-dict objects to be '
- 'serialized set the safe parameter to False')
- kwargs.setdefault('content_type', 'application/json')
- data = json.dumps(data, cls=encoder)
- super(JsonResponse, self).__init__(content=data, **kwargs)
- def get_app_list(context, order=True):
- admin_site = get_admin_site(context)
- request = context['request']
- app_dict = {}
- for model, model_admin in admin_site._registry.items():
- app_label = model._meta.app_label
- try:
- has_module_perms = model_admin.has_module_permission(request)
- except AttributeError:
- has_module_perms = request.user.has_module_perms(app_label) # Fix Django < 1.8 issue
- if has_module_perms:
- perms = model_admin.get_model_perms(request)
- # Check whether user has any perm for this module.
- # If so, add the module to the model_list.
- if True in perms.values():
- info = (app_label, model._meta.model_name)
- model_dict = {
- 'name': capfirst(model._meta.verbose_name_plural),
- 'object_name': model._meta.object_name,
- 'perms': perms,
- 'model_name': model._meta.model_name
- }
- if perms.get('change', False):
- try:
- model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin_site.name)
- except NoReverseMatch:
- pass
- if perms.get('add', False):
- try:
- model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin_site.name)
- except NoReverseMatch:
- pass
- if app_label in app_dict:
- app_dict[app_label]['models'].append(model_dict)
- else:
- try:
- name = apps.get_app_config(app_label).verbose_name
- except NameError:
- name = app_label.title()
- app_dict[app_label] = {
- 'name': name,
- 'app_label': app_label,
- 'app_url': reverse(
- 'admin:app_list',
- kwargs={'app_label': app_label},
- current_app=admin_site.name,
- ),
- 'has_module_perms': has_module_perms,
- 'models': [model_dict],
- }
- # Sort the apps alphabetically.
- app_list = list(app_dict.values())
- if order:
- app_list.sort(key=lambda x: x['name'].lower())
- # Sort the models alphabetically within each app.
- for app in app_list:
- app['models'].sort(key=lambda x: x['name'])
- return app_list
- def get_admin_site(context):
- try:
- current_resolver = resolve(context.get('request').path)
- index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0]))
- if hasattr(index_resolver.func, 'admin_site'):
- return index_resolver.func.admin_site
- for func_closure in index_resolver.func.__closure__:
- if isinstance(func_closure.cell_contents, AdminSite):
- return func_closure.cell_contents
- except:
- pass
- return admin.site
- def get_admin_site_name(context):
- return get_admin_site(context).name
- class LazyDateTimeEncoder(json.JSONEncoder):
- def default(self, obj):
- if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date):
- return obj.isoformat()
- elif isinstance(obj, Promise):
- return force_text(obj)
- return self.encode(obj)
- def get_model_instance_label(instance):
- if getattr(instance, "related_label", None):
- return instance.related_label()
- return smart_text(instance)
- class SuccessMessageMixin(object):
- """
- Adds a success message on successful form submission.
- """
- success_message = ''
- def form_valid(self, form):
- response = super(SuccessMessageMixin, self).form_valid(form)
- success_message = self.get_success_message(form.cleaned_data)
- if success_message:
- messages.success(self.request, success_message)
- return response
- def get_success_message(self, cleaned_data):
- return self.success_message % cleaned_data
- def get_model_queryset(admin_site, model, request, preserved_filters=None):
- model_admin = admin_site._registry.get(model)
- try:
- changelist_url = reverse('%s:%s_%s_changelist' % (
- admin_site.name,
- model._meta.app_label,
- model._meta.model_name
- ))
- except NoReverseMatch:
- return
- changelist_filters = None
- if preserved_filters:
- changelist_filters = preserved_filters.get('_changelist_filters')
- if changelist_filters:
- changelist_url += '?' + changelist_filters
- if model_admin:
- queryset = model_admin.get_queryset(request)
- else:
- queryset = model.objects
- list_display = model_admin.get_list_display(request)
- list_display_links = model_admin.get_list_display_links(request, list_display)
- list_filter = model_admin.get_list_filter(request)
- search_fields = model_admin.get_search_fields(request) \
- if hasattr(model_admin, 'get_search_fields') else model_admin.search_fields
- list_select_related = model_admin.get_list_select_related(request) \
- if hasattr(model_admin, 'get_list_select_related') else model_admin.list_select_related
- actions = model_admin.get_actions(request)
- if actions:
- list_display = ['action_checkbox'] + list(list_display)
- ChangeList = model_admin.get_changelist(request)
- try:
- cl = ChangeList(
- request, model, list_display, list_display_links, list_filter, model_admin.date_hierarchy, search_fields,
- list_select_related, model_admin.list_per_page, model_admin.list_max_show_all, model_admin.list_editable,
- model_admin)
- queryset = cl.get_queryset(request)
- except IncorrectLookupParameters:
- pass
- return queryset
- def get_possible_language_codes():
- language_code = translation.get_language()
- language_code = language_code.replace('_', '-').lower()
- language_codes = []
- # making dialect part uppercase
- split = language_code.split('-', 2)
- if len(split) == 2:
- language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0]
- language_codes.append(language_code)
- # adding language code without dialect part
- if len(split) == 2:
- language_codes.append(split[0].lower())
- return language_codes
- def get_original_menu_items(context):
- if context.get('user') and user_is_authenticated(context['user']):
- pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True)
- else:
- pinned_apps = []
- original_app_list = get_app_list(context)
- return map(lambda app: {
- 'app_label': app['app_label'],
- 'url': app['app_url'],
- 'url_blank': False,
- 'label': app.get('name', capfirst(_(app['app_label']))),
- 'has_perms': app.get('has_module_perms', False),
- 'models': list(map(lambda model: {
- 'url': model.get('admin_url'),
- 'url_blank': False,
- 'name': model['model_name'],
- 'object_name': model['object_name'],
- 'label': model.get('name', model['object_name']),
- 'has_perms': any(model.get('perms', {}).values()),
- }, app['models'])),
- 'pinned': app['app_label'] in pinned_apps,
- 'custom': False
- }, original_app_list)
- def get_menu_item_url(url, original_app_list):
- if isinstance(url, dict):
- url_type = url.get('type')
- if url_type == 'app':
- return original_app_list[url['app_label']]['url']
- elif url_type == 'model':
- models = dict(map(
- lambda x: (x['name'], x['url']),
- original_app_list[url['app_label']]['models']
- ))
- return models[url['model']]
- elif url_type == 'reverse':
- return reverse(url['name'], args=url.get('args'), kwargs=url.get('kwargs'))
- elif isinstance(url, str):
- return url
- def get_menu_items(context):
- pinned_apps = PinnedApplication.objects.filter(user=context['user'].pk).values_list('app_label', flat=True)
- original_app_list = OrderedDict(map(lambda app: (app['app_label'], app), get_original_menu_items(context)))
- custom_app_list = settings.JET_SIDE_MENU_ITEMS
- custom_app_list_deprecated = settings.JET_SIDE_MENU_CUSTOM_APPS
- if custom_app_list not in (None, False):
- if isinstance(custom_app_list, dict):
- admin_site = get_admin_site(context)
- custom_app_list = custom_app_list.get(admin_site.name, [])
- app_list = []
- def get_menu_item_app_model(app_label, data):
- item = {'has_perms': True}
- if 'name' in data:
- parts = data['name'].split('.', 2)
- if len(parts) > 1:
- app_label, name = parts
- else:
- name = data['name']
- if app_label in original_app_list:
- models = dict(map(
- lambda x: (x['name'], x),
- original_app_list[app_label]['models']
- ))
- if name in models:
- item = models[name].copy()
- if 'label' in data:
- item['label'] = data['label']
- if 'url' in data:
- item['url'] = get_menu_item_url(data['url'], original_app_list)
- if 'url_blank' in data:
- item['url_blank'] = data['url_blank']
- if 'permissions' in data:
- item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions'])
- return item
- def get_menu_item_app(data):
- app_label = data.get('app_label')
- if not app_label:
- if 'label' not in data:
- raise Exception('Custom menu items should at least have \'label\' or \'app_label\' key')
- app_label = 'custom_%s' % slugify(data['label'], allow_unicode=True)
- if app_label in original_app_list:
- item = original_app_list[app_label].copy()
- else:
- item = {'app_label': app_label, 'has_perms': True}
- if 'label' in data:
- item['label'] = data['label']
- if 'items' in data:
- item['items'] = list(map(lambda x: get_menu_item_app_model(app_label, x), data['items']))
- if 'url' in data:
- item['url'] = get_menu_item_url(data['url'], original_app_list)
- if 'url_blank' in data:
- item['url_blank'] = data['url_blank']
- if 'permissions' in data:
- item['has_perms'] = item.get('has_perms', True) and context['user'].has_perms(data['permissions'])
- item['pinned'] = item['app_label'] in pinned_apps
- return item
- for data in custom_app_list:
- item = get_menu_item_app(data)
- app_list.append(item)
- elif custom_app_list_deprecated not in (None, False):
- app_dict = {}
- models_dict = {}
- for app in original_app_list.values():
- app_label = app['app_label']
- app_dict[app_label] = app
- for model in app['models']:
- if app_label not in models_dict:
- models_dict[app_label] = {}
- models_dict[app_label][model['object_name']] = model
- app['items'] = []
- app_list = []
- if isinstance(custom_app_list_deprecated, dict):
- admin_site = get_admin_site(context)
- custom_app_list_deprecated = custom_app_list_deprecated.get(admin_site.name, [])
- for item in custom_app_list_deprecated:
- app_label, models = item
- if app_label in app_dict:
- app = app_dict[app_label]
- for model_label in models:
- if model_label == '__all__':
- app['items'] = models_dict[app_label].values()
- break
- elif model_label in models_dict[app_label]:
- model = models_dict[app_label][model_label]
- app['items'].append(model)
- app_list.append(app)
- else:
- def map_item(item):
- item['items'] = item['models']
- return item
- app_list = list(map(map_item, original_app_list.values()))
- current_found = False
- for app in app_list:
- if not current_found:
- for model in app['items']:
- if not current_found and model.get('url') and context['request'].path.startswith(model['url']):
- model['current'] = True
- current_found = True
- else:
- model['current'] = False
- if not current_found and app.get('url') and context['request'].path.startswith(app['url']):
- app['current'] = True
- current_found = True
- else:
- app['current'] = False
- return app_list
- def context_to_dict(context):
- if isinstance(context, Context):
- flat = {}
- for d in context.dicts:
- flat.update(d)
- context = flat
- return context
- def user_is_authenticated(user):
- if not hasattr(user.is_authenticated, '__call__'):
- return user.is_authenticated
- else:
- return user.is_authenticated()
|