utils.py 7.4 KB

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