actions.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 __nonzero__(self):
  17. return bool(self.available_actions)
  18. def get_available_actions(self, kwargs):
  19. raise NotImplementedError("get_available_actions has to return list "
  20. "of dicts with allowed actions")
  21. def resolve_action(self, request):
  22. action_name = request.POST.get(self.query_key)
  23. for action in self.available_actions:
  24. if action['action'] == action_name:
  25. if ':' in action_name:
  26. action_bits = action_name.split(':')
  27. action_name = action_bits[0]
  28. action_arg = action_bits[1]
  29. else:
  30. action_arg = None
  31. action_callable = 'action_%s' % action_name
  32. return getattr(self, action_callable), action_arg
  33. else:
  34. raise ModerationError(self.invalid_action_message)
  35. def clean_selection(self, data):
  36. filtered_data = []
  37. for pk in data[:50]: # a tiny fail-safe to avoid too big workloads
  38. try:
  39. filtered_data.append(int(pk))
  40. except ValueError:
  41. pass
  42. if not filtered_data:
  43. raise ModerationError(self.select_items_message)
  44. return filtered_data
  45. def handle_post(self, request, target):
  46. try:
  47. if self.is_mass_action:
  48. return self.handle_mass_action(request, target)
  49. else:
  50. return self.handle_single_action(request, target)
  51. except ModerationError as e:
  52. if request.is_ajax():
  53. raise AjaxError(e.message, 406)
  54. else:
  55. messages.error(request, e.message)
  56. return False
  57. def handle_mass_action(self, request, queryset):
  58. action, action_arg = self.resolve_action(request)
  59. self.selected_ids = self.clean_selection(
  60. request.POST.getlist('item', []))
  61. filtered_queryset = queryset.filter(pk__in=self.selected_ids)
  62. if filtered_queryset.exists():
  63. if action_arg:
  64. response = action(request, filtered_queryset, action_arg)
  65. else:
  66. response = action(request, filtered_queryset)
  67. if response:
  68. return response
  69. elif request.is_ajax():
  70. raise AjaxError(self.invalid_action_message, 406)
  71. else:
  72. # prepare default response: page reload
  73. return redirect(request.path)
  74. else:
  75. raise ModerationError(self.select_items_message)
  76. def handle_single_action(self, request, target):
  77. action, action_arg = self.resolve_action(request)
  78. if action_arg:
  79. response = action(request, target, action_arg)
  80. else:
  81. response = action(request, target)
  82. if response:
  83. return response
  84. elif request.is_ajax():
  85. raise AjaxError(self.invalid_action_message, 406)
  86. else:
  87. # prepare default response: page reload
  88. return redirect(request.path)
  89. def get_list(self):
  90. return self.available_actions
  91. def get_selected_ids(self):
  92. return self.selected_ids