generic.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. from django.contrib import messages
  2. from django.core.paginator import Paginator, EmptyPage
  3. from django.shortcuts import redirect
  4. from django.utils.translation import ugettext_lazy as _
  5. from django.views.generic import View
  6. from misago.core.exceptions import ExplicitFirstPage
  7. from misago.admin import site
  8. from misago.admin.views import render
  9. class AdminBaseMixin(object):
  10. """
  11. Admin mixin abstraciton used for configuring admin CRUD views.
  12. Takes following attributes:
  13. Model = Model instance
  14. message_404 = string used in "requested item not found" messages
  15. root_link = name of link leading to root action (eg. list of all items
  16. template_dir = directory with templates
  17. """
  18. Model = None
  19. message_404 = None
  20. root_link = None
  21. template_dir = None
  22. def get_model(self):
  23. return self.Model
  24. class AdminView(View):
  25. def final_template(self):
  26. return '%s/%s' % (self.template_dir, self.template)
  27. def get_target(self, target):
  28. Model = self.get_model()
  29. return Model.objects.get(id=target)
  30. def _get_target(self, request, kwargs):
  31. """
  32. get_target is called by view to fetch item from DB
  33. """
  34. Model = self.get_model()
  35. try:
  36. return self.get_target(target)
  37. except Model.DoesNotExist:
  38. messages.error(request, self.message_404)
  39. return redirect(self.root_link)
  40. def current_link(self, request):
  41. matched_url = request.resolver_match.url_name
  42. return '%s:%s' % (request.resolver_match.namespace, matched_url)
  43. def render(self, request, context=None):
  44. context = context or {}
  45. context['root_link'] = self.root_link
  46. context['current_link'] = self.current_link(request)
  47. return render(request, self.final_template(), context)
  48. class ItemsList(AdminView):
  49. """
  50. Admin items list view
  51. Uses following attributes:
  52. template = template name used to render items list
  53. items_per_page = number of items displayed on single page
  54. (enter 0 or don't define for no pagination)
  55. ordering = tuple of tuples defining allowed orderings
  56. typles should follow this format: (name, order_by)
  57. """
  58. template = 'list.html'
  59. items_per_page = 0
  60. ordering = None
  61. def get_queryset(self):
  62. return self.get_model().objects.all()
  63. def paginate_items(self, context, page):
  64. try:
  65. page = int(page)
  66. if page == 1:
  67. raise ExplicitFirstPage()
  68. elif page == 0:
  69. page = 1
  70. except ValueError:
  71. page_no = 1
  72. context['paginator'] = Paginator(context['items'],
  73. self.items_per_page,
  74. allow_empty_first_page=True)
  75. context['page'] = context['paginator'].page(page)
  76. context['items'] = context['page'].object_list
  77. def set_filters(self, request):
  78. pass
  79. def filter_items(self, request, context):
  80. context['is_filtering'] = False
  81. def ordering_session_key(self):
  82. return 'misago_admin_%s_order_by' % self.root_link
  83. def set_ordering(self, request, new_order):
  84. for order in self.ordering:
  85. if order[1] == new_order:
  86. request.session[self.ordering_session_key()] = order[1]
  87. return redirect(self.current_link(request))
  88. else:
  89. messages.error(request, _("New sorting method is incorrect."))
  90. raise ValueError()
  91. def order_items(self, request, context):
  92. current_ordering = request.session.get(self.ordering_session_key())
  93. for order in self.ordering:
  94. order_as_dict = {
  95. 'name': order[0],
  96. 'order_by': order[1],
  97. 'type': 'desc' if order[1][0] == '-' else 'asc',
  98. }
  99. if order[1] == current_ordering:
  100. context['order'] = order_as_dict
  101. context['items'] = context['items'].order_by(
  102. order_as_dict['order_by'])
  103. else:
  104. context['order_by'].append(order_as_dict)
  105. if not context['order']:
  106. current_ordering = context['order_by'].pop(0)
  107. context['order'] = current_ordering
  108. context['items'] = context['items'].order_by(
  109. current_ordering['order_by'])
  110. def dispatch(self, request, *args, **kwargs):
  111. context = {
  112. 'items': self.get_queryset(),
  113. 'paginator': None,
  114. 'page': None,
  115. 'order_by': [],
  116. 'order': None,
  117. }
  118. if self.ordering:
  119. if request.method == 'POST' and 'order_by' in request.POST:
  120. try:
  121. return self.set_ordering(request,
  122. request.POST.get('order_by'))
  123. except ValueError:
  124. pass
  125. self.order_items(request, context)
  126. if self.items_per_page:
  127. self.paginate_items(context, kwargs.get('page', 0))
  128. return self.render(request, context)
  129. class ItemView(AdminView):
  130. pass
  131. class FormView(ItemView):
  132. template = 'form.html'
  133. def dispatch(self, request, *args, **kwargs):
  134. pass
  135. class ButtonView(ItemView):
  136. def get(self, request, *args, **kwargs):
  137. pass
  138. def post(self, request, *args, **kwargs):
  139. pass