actions.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. from django.contrib import messages
  2. from django.shortcuts import redirect
  3. from django.utils.translation import ugettext_lazy as _
  4. from misago.core.exceptions import AjaxError
  5. from misago.threads.moderation import ModerationError
  6. __all__ = ['ActionsBase']
  7. class ActionsBase(object):
  8. query_key = 'action'
  9. invalid_action_message = _("Requested action is invalid.")
  10. def __init__(self, **kwargs):
  11. if kwargs.get('user').is_authenticated():
  12. self.available_actions = self.get_available_actions(kwargs)
  13. else:
  14. self.available_actions = []
  15. self.selected_ids = []
  16. def get_available_actions(self, kwargs):
  17. raise NotImplementedError("get_available_actions has to return list "
  18. "of dicts with allowed actions")
  19. def resolve_action(self, request):
  20. action_name = request.POST.get(self.query_key)
  21. for action in self.available_actions:
  22. if action['action'] == action_name:
  23. if ':' in action_name:
  24. action_bits = action_name.split(':')
  25. action_name = action_bits[0]
  26. action_arg = action_bits[1]
  27. else:
  28. action_arg = None
  29. action_callable = 'action_%s' % action_name
  30. return getattr(self, action_callable), action_arg
  31. else:
  32. raise ModerationError(self.invalid_action_message)
  33. def clean_selection(self, data):
  34. filtered_data = []
  35. for pk in data[:50]: # a tiny fail-safe to avoid too big workloads
  36. try:
  37. filtered_data.append(int(pk))
  38. except ValueError:
  39. pass
  40. if not filtered_data:
  41. raise ModerationError(self.select_items_message)
  42. return filtered_data
  43. def handle_post(self, request, target):
  44. try:
  45. if self.is_mass_action:
  46. return self.handle_mass_action(request, target)
  47. else:
  48. return self.handle_single_action(request, target)
  49. except ModerationError as e:
  50. if request.is_ajax():
  51. raise AjaxError(e.message, 406)
  52. else:
  53. messages.error(request, e.message)
  54. return False
  55. def handle_mass_action(self, request, queryset):
  56. action, action_arg = self.resolve_action(request)
  57. self.selected_ids = self.clean_selection(
  58. request.POST.getlist('thread', []))
  59. filtered_queryset = queryset.filter(pk__in=self.selected_ids)
  60. if filtered_queryset.exists():
  61. if action_arg:
  62. response = action(request, filtered_queryset, action_arg)
  63. else:
  64. response = action(request, filtered_queryset)
  65. if response:
  66. return response
  67. elif request.is_ajax():
  68. raise AjaxError(self.invalid_action_message, 406)
  69. else:
  70. # prepare default response: page reload
  71. return redirect(request.path)
  72. else:
  73. raise ModerationError(self.select_items_message)
  74. def handle_single_action(self, request, target):
  75. action, action_arg = self.resolve_action(request)
  76. if action_arg:
  77. response = action(request, target, action_arg)
  78. else:
  79. response = action(request, target)
  80. if response:
  81. return response
  82. elif request.is_ajax():
  83. raise AjaxError(self.invalid_action_message, 406)
  84. else:
  85. # prepare default response: page reload
  86. return redirect(request.path)
  87. def get_list(self):
  88. return self.available_actions
  89. def get_selected_ids(self):
  90. return self.selected_ids