utils.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import datetime
  2. import json
  3. from django.utils import translation
  4. try:
  5. from django.apps.registry import apps
  6. except ImportError:
  7. try:
  8. from django.apps import apps # Fix Django 1.7 import issue
  9. except ImportError:
  10. pass
  11. from django.core.serializers.json import DjangoJSONEncoder
  12. from django.http import HttpResponse
  13. from django.core.urlresolvers import reverse, resolve, NoReverseMatch
  14. from django.contrib.admin import AdminSite
  15. from django.utils.encoding import smart_text
  16. from django.utils.text import capfirst
  17. from django.contrib import messages
  18. from django.utils.encoding import force_text
  19. from django.utils.functional import Promise
  20. from django.contrib.admin.options import IncorrectLookupParameters
  21. from django.core import urlresolvers
  22. from django.contrib import admin
  23. from django.test.client import RequestFactory
  24. class JsonResponse(HttpResponse):
  25. """
  26. An HTTP response class that consumes data to be serialized to JSON.
  27. :param data: Data to be dumped into json. By default only ``dict`` objects
  28. are allowed to be passed due to a security flaw before EcmaScript 5. See
  29. the ``safe`` parameter for more information.
  30. :param encoder: Should be an json encoder class. Defaults to
  31. ``django.core.serializers.json.DjangoJSONEncoder``.
  32. :param safe: Controls if only ``dict`` objects may be serialized. Defaults
  33. to ``True``.
  34. """
  35. def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, **kwargs):
  36. if safe and not isinstance(data, dict):
  37. raise TypeError('In order to allow non-dict objects to be '
  38. 'serialized set the safe parameter to False')
  39. kwargs.setdefault('content_type', 'application/json')
  40. data = json.dumps(data, cls=encoder)
  41. super(JsonResponse, self).__init__(content=data, **kwargs)
  42. def get_app_list(context, order=True):
  43. admin_site = get_admin_site(context)
  44. request = context['request']
  45. app_dict = {}
  46. for model, model_admin in admin_site._registry.items():
  47. app_label = model._meta.app_label
  48. try:
  49. has_module_perms = model_admin.has_module_permission(request)
  50. except AttributeError:
  51. has_module_perms = request.user.has_module_perms(app_label) # Fix Django < 1.8 issue
  52. if has_module_perms:
  53. perms = model_admin.get_model_perms(request)
  54. # Check whether user has any perm for this module.
  55. # If so, add the module to the model_list.
  56. if True in perms.values():
  57. info = (app_label, model._meta.model_name)
  58. model_dict = {
  59. 'name': capfirst(model._meta.verbose_name_plural),
  60. 'object_name': model._meta.object_name,
  61. 'perms': perms,
  62. }
  63. if perms.get('change', False):
  64. try:
  65. model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=admin_site.name)
  66. except NoReverseMatch:
  67. pass
  68. if perms.get('add', False):
  69. try:
  70. model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=admin_site.name)
  71. except NoReverseMatch:
  72. pass
  73. if app_label in app_dict:
  74. app_dict[app_label]['models'].append(model_dict)
  75. else:
  76. try:
  77. name = apps.get_app_config(app_label).verbose_name
  78. except NameError:
  79. name = app_label.title()
  80. app_dict[app_label] = {
  81. 'name': name,
  82. 'app_label': app_label,
  83. 'app_url': reverse(
  84. 'admin:app_list',
  85. kwargs={'app_label': app_label},
  86. current_app=admin_site.name,
  87. ),
  88. 'has_module_perms': has_module_perms,
  89. 'models': [model_dict],
  90. }
  91. # Sort the apps alphabetically.
  92. app_list = list(app_dict.values())
  93. if order:
  94. app_list.sort(key=lambda x: x['name'].lower())
  95. # Sort the models alphabetically within each app.
  96. for app in app_list:
  97. app['models'].sort(key=lambda x: x['name'])
  98. return app_list
  99. def get_admin_site(context):
  100. try:
  101. current_resolver = resolve(context.get('request').path)
  102. index_resolver = resolve(reverse('%s:index' % current_resolver.namespaces[0]))
  103. if hasattr(index_resolver.func, 'admin_site'):
  104. return index_resolver.func.admin_site
  105. for func_closure in index_resolver.func.__closure__:
  106. if isinstance(func_closure.cell_contents, AdminSite):
  107. return func_closure.cell_contents
  108. except:
  109. pass
  110. return admin.site
  111. def get_admin_site_name(context):
  112. return get_admin_site(context).name
  113. class LazyDateTimeEncoder(json.JSONEncoder):
  114. def default(self, obj):
  115. if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date):
  116. return obj.isoformat()
  117. elif isinstance(obj, Promise):
  118. return force_text(obj)
  119. return self.encode(obj)
  120. def get_model_instance_label(instance):
  121. if getattr(instance, "related_label", None):
  122. return instance.related_label()
  123. return smart_text(instance)
  124. class SuccessMessageMixin(object):
  125. """
  126. Adds a success message on successful form submission.
  127. """
  128. success_message = ''
  129. def form_valid(self, form):
  130. response = super(SuccessMessageMixin, self).form_valid(form)
  131. success_message = self.get_success_message(form.cleaned_data)
  132. if success_message:
  133. messages.success(self.request, success_message)
  134. return response
  135. def get_success_message(self, cleaned_data):
  136. return self.success_message % cleaned_data
  137. def get_model_queryset(admin_site, model, preserved_filters=None):
  138. model_admin = admin_site._registry.get(model)
  139. changelist_url = urlresolvers.reverse('%s:%s_%s_changelist' % (
  140. admin_site.name,
  141. model._meta.app_label,
  142. model._meta.model_name
  143. ))
  144. changelist_filters = None
  145. if preserved_filters:
  146. changelist_filters = preserved_filters.get('_changelist_filters')
  147. if changelist_filters:
  148. changelist_url += '?' + changelist_filters
  149. request = RequestFactory().get(changelist_url)
  150. if model_admin:
  151. queryset = model_admin.get_queryset(request)
  152. else:
  153. queryset = model.objects
  154. list_display = model_admin.get_list_display(request)
  155. list_display_links = model_admin.get_list_display_links(request, list_display)
  156. list_filter = model_admin.get_list_filter(request)
  157. search_fields = model_admin.get_search_fields(request) \
  158. if hasattr(model_admin, 'get_search_fields') else model_admin.search_fields
  159. list_select_related = model_admin.get_list_select_related(request) \
  160. if hasattr(model_admin, 'get_list_select_related') else model_admin.list_select_related
  161. actions = model_admin.get_actions(request)
  162. if actions:
  163. list_display = ['action_checkbox'] + list(list_display)
  164. ChangeList = model_admin.get_changelist(request)
  165. try:
  166. cl = ChangeList(
  167. request, model, list_display, list_display_links, list_filter, model_admin.date_hierarchy, search_fields,
  168. list_select_related, model_admin.list_per_page, model_admin.list_max_show_all, model_admin.list_editable,
  169. model_admin)
  170. queryset = cl.get_queryset(request)
  171. except IncorrectLookupParameters:
  172. pass
  173. return queryset
  174. def get_possible_language_codes():
  175. language_code = translation.get_language()
  176. language_code = language_code.replace('_', '-').lower()
  177. language_codes = []
  178. # making dialect part uppercase
  179. split = language_code.split('-', 2)
  180. if len(split) == 2:
  181. language_code = '%s-%s' % (split[0].lower(), split[1].upper()) if split[0] != split[1] else split[0]
  182. language_codes.append(language_code)
  183. # adding language code without dialect part
  184. if len(split) == 2:
  185. language_codes.append(split[0].lower())
  186. return language_codes