list.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. from urllib import urlencode
  2. from django.core.paginator import Paginator, EmptyPage
  3. from django.shortcuts import redirect
  4. from misago.core.exceptions import ExplicitFirstPage
  5. from misago.admin.views.generic.base import AdminView
  6. class ListView(AdminView):
  7. """
  8. Admin items list view
  9. Uses following attributes:
  10. template = template name used to render items list
  11. items_per_page = number of items displayed on single page
  12. (enter 0 or don't define for no pagination)
  13. ordering = tuple of tuples defining allowed orderings
  14. typles should follow this format: (name, order_by)
  15. """
  16. template = 'list.html'
  17. items_per_page = 0
  18. ordering = None
  19. extra_actions = None
  20. @classmethod
  21. def add_item_action(cls, name, icon, link, style=None):
  22. if not cls.extra_actions:
  23. cls.extra_actions = []
  24. cls.extra_actions.append({
  25. 'name': name,
  26. 'icon': icon,
  27. 'link': link,
  28. 'style': style,
  29. })
  30. def get_queryset(self):
  31. return self.get_model().objects.all()
  32. def paginate_items(self, context, page):
  33. try:
  34. page = int(page)
  35. if page == 1:
  36. raise ExplicitFirstPage()
  37. elif page == 0:
  38. page = 1
  39. except ValueError:
  40. page_no = 1
  41. context['paginator'] = Paginator(context['items'],
  42. self.items_per_page,
  43. allow_empty_first_page=True)
  44. context['page'] = context['paginator'].page(page)
  45. context['items'] = context['page'].object_list
  46. @property
  47. def filters_token(self):
  48. return '%s:filters' % self.root_link
  49. def search_form(self, request, context):
  50. pass
  51. def filter_items(self, context):
  52. pass
  53. @property
  54. def ordering_session_key(self):
  55. return 'misago_admin_%s_order_by' % self.root_link
  56. def get_ordering_from_get(self, request):
  57. sort = request.GET.get('sort')
  58. if request.GET.get('direction') == 'desc':
  59. new_ordering = '-%s' % sort
  60. elif request.GET.get('direction') == 'asc':
  61. new_ordering = sort
  62. else:
  63. new_ordering = '?nope'
  64. return self.clean_ordering(new_ordering)
  65. def get_ordering_from_session(self, request):
  66. new_ordering = request.session.get(self.ordering_session_key)
  67. return self.clean_ordering(new_ordering)
  68. def get_default_ordering(self):
  69. pass
  70. def clean_ordering(self, new_ordering):
  71. for order_by, name in self.ordering:
  72. if order_by == new_ordering:
  73. return order_by
  74. else:
  75. return None
  76. def get_ordering_methods(self, request):
  77. methods = {
  78. 'GET': self.get_ordering_from_get(request),
  79. 'session': self.get_ordering_from_session(request),
  80. 'default': self.get_default_ordering(),
  81. }
  82. if methods['GET'] and methods['GET'] != methods['session']:
  83. request.session[self.ordering_session_key] = methods['GET']
  84. return methods
  85. def get_ordering_method(self, methods):
  86. for method in ('GET', 'session', 'default'):
  87. if methods.get(method):
  88. return methods.get(method)
  89. def order_items(self, method, context):
  90. for order_by, name in self.ordering:
  91. order_as_dict = {
  92. 'type': 'desc' if order_by[0] == '-' else 'asc',
  93. 'order_by': order_by,
  94. 'name': name,
  95. }
  96. if order_by == method:
  97. context['order'] = order_as_dict
  98. context['items'] = context['items'].order_by(
  99. order_as_dict['order_by'])
  100. elif order_as_dict['name']:
  101. if order_as_dict['type'] == 'desc':
  102. order_as_dict['order_by'] = order_as_dict['order_by'][1:]
  103. context['order_by'].append(order_as_dict)
  104. def make_querystrings(self, request, context):
  105. values = {}
  106. filter_values = {}
  107. order_values = {}
  108. if context['active_filters']:
  109. filter_values = context['active_filters']
  110. values.update(filter_values)
  111. if context['order']:
  112. order_values = {
  113. 'sort': context['order']['order_by'],
  114. 'direction': context['order']['type'],
  115. }
  116. values.update(order_values)
  117. if values:
  118. context['querystring'] = '?%s' % urlencode(values)
  119. if order_values:
  120. context['querystring_order'] = '?%s' % urlencode(order_values)
  121. if filter_values:
  122. context['querystring_filter'] = '?%s' % urlencode(filter_values)
  123. def dispatch(self, request, *args, **kwargs):
  124. active_filters = request.session.get(self.filters_token, None)
  125. extra_actions_list = self.extra_actions or []
  126. set_querystring = False
  127. context = {
  128. 'items': self.get_queryset(),
  129. 'paginator': None,
  130. 'page': None,
  131. 'order_by': [],
  132. 'order': None,
  133. 'search_form': None,
  134. 'active_filters': active_filters,
  135. 'querystring': '',
  136. 'querystring_order': '',
  137. 'querystring_filter': '',
  138. 'extra_actions': extra_actions_list,
  139. 'extra_actions_len': len(extra_actions_list),
  140. }
  141. if self.ordering:
  142. ordering_methods = self.get_ordering_methods(request)
  143. current_method = self.get_ordering_method(ordering_methods)
  144. self.order_items(current_method, context)
  145. if context['order_by'] and not ordering_methods.get('GET'):
  146. set_querystring = True
  147. self.search_form(request, context)
  148. if active_filters:
  149. self.filter_items(context)
  150. if self.items_per_page:
  151. self.paginate_items(context, kwargs.get('page', 0))
  152. self.make_querystrings(request, context)
  153. if set_querystring:
  154. return redirect('%s%s' % (request.path, context['querystring']))
  155. return self.render(request, context)