categoriesadmin.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. from django.contrib import messages
  2. from django.shortcuts import redirect
  3. from django.utils.translation import ugettext_lazy as _
  4. from misago.acl import version as acl_version
  5. from misago.admin.views import generic
  6. from misago.threads.threadtypes import trees_map
  7. from ..forms import CategoryFormFactory, DeleteFormFactory
  8. from ..models import THREADS_ROOT_NAME, Category, RoleCategoryACL
  9. class CategoryAdmin(generic.AdminBaseMixin):
  10. root_link = 'misago:admin:categories:nodes:index'
  11. Model = Category
  12. templates_dir = 'misago/admin/categories'
  13. message_404 = _("Requested category does not exist.")
  14. def get_target(self, kwargs):
  15. target = super(CategoryAdmin, self).get_target(kwargs)
  16. threads_tree_id = trees_map.get_tree_id_for_root(THREADS_ROOT_NAME)
  17. target_is_special = bool(target.special_role)
  18. target_not_in_categories_tree = target.tree_id != threads_tree_id
  19. if target.pk and (target_is_special or target_not_in_categories_tree):
  20. raise Category.DoesNotExist()
  21. else:
  22. return target
  23. class CategoriesList(CategoryAdmin, generic.ListView):
  24. def get_queryset(self):
  25. return Category.objects.all_categories()
  26. def process_context(self, request, context):
  27. context['items'] = [f for f in context['items']]
  28. children_lists = {}
  29. for i, item in enumerate(context['items']):
  30. item.level_range = range(item.level - 1)
  31. item.first = False
  32. item.last = False
  33. children_lists.setdefault(item.parent_id, []).append(item)
  34. for level_items in children_lists.values():
  35. level_items[0].first = True
  36. level_items[-1].last = True
  37. return context
  38. class CategoryFormMixin(object):
  39. def create_form_type(self, request, target):
  40. return CategoryFormFactory(target)
  41. def handle_form(self, form, request, target):
  42. if form.instance.pk:
  43. if form.instance.parent_id != form.cleaned_data['new_parent'].pk:
  44. form.instance.move_to(
  45. form.cleaned_data['new_parent'], position='last-child')
  46. form.instance.save()
  47. if form.instance.parent_id != form.cleaned_data['new_parent'].pk:
  48. Category.objects.clear_cache()
  49. else:
  50. form.instance.insert_at(form.cleaned_data['new_parent'],
  51. position='last-child',
  52. save=True,
  53. )
  54. Category.objects.clear_cache()
  55. if form.cleaned_data.get('copy_permissions'):
  56. form.instance.category_role_set.all().delete()
  57. copy_from = form.cleaned_data['copy_permissions']
  58. copied_acls = []
  59. for acl in copy_from.category_role_set.all():
  60. copied_acls.append(RoleCategoryACL(
  61. role_id=acl.role_id,
  62. category=form.instance,
  63. category_role_id=acl.category_role_id,
  64. ))
  65. if copied_acls:
  66. RoleCategoryACL.objects.bulk_create(copied_acls)
  67. acl_version.invalidate()
  68. messages.success(request, self.message_submit % {'name': target.name})
  69. class NewCategory(CategoryFormMixin, CategoryAdmin, generic.ModelFormView):
  70. message_submit = _('New category "%(name)s" has been saved.')
  71. class EditCategory(CategoryFormMixin, CategoryAdmin, generic.ModelFormView):
  72. message_submit = _('Category "%(name)s" has been edited.')
  73. class DeleteCategory(CategoryAdmin, generic.ModelFormView):
  74. message_submit = _('Category "%(name)s" has been deleted.')
  75. template = 'delete.html'
  76. def create_form_type(self, request, target):
  77. return DeleteFormFactory(target)
  78. def handle_form(self, form, request, target):
  79. move_children_to = form.cleaned_data.get('move_children_to')
  80. move_threads_to = form.cleaned_data.get('move_threads_to')
  81. if move_children_to:
  82. for child in target.get_children():
  83. # refresh child and new parent
  84. move_children_to = Category.objects.get(pk=move_children_to.pk)
  85. child = Category.objects.get(pk=child.pk)
  86. child.move_to(move_children_to, 'last-child')
  87. if move_threads_to and child.pk == move_threads_to.pk:
  88. move_threads_to = child
  89. else:
  90. for child in target.get_descendants().order_by('-lft'):
  91. child.delete_content()
  92. child.delete()
  93. if move_threads_to:
  94. target.move_content(move_threads_to)
  95. move_threads_to.synchronize()
  96. move_threads_to.save()
  97. else:
  98. target.delete_content()
  99. # refresh instance
  100. instance = Category.objects.get(pk=form.instance.pk)
  101. instance.delete()
  102. messages.success(request, self.message_submit % {'name': target.name})
  103. return redirect(self.root_link)
  104. class MoveDownCategory(CategoryAdmin, generic.ButtonView):
  105. def button_action(self, request, target):
  106. try:
  107. other_target = target.get_next_sibling()
  108. except Category.DoesNotExist:
  109. other_target = None
  110. if other_target:
  111. Category.objects.move_node(target, other_target, 'right')
  112. Category.objects.clear_cache()
  113. message = _('Category "%(name)s" has been moved below "%(other)s".')
  114. targets_names = {'name': target.name, 'other': other_target.name}
  115. messages.success(request, message % targets_names)
  116. class MoveUpCategory(CategoryAdmin, generic.ButtonView):
  117. def button_action(self, request, target):
  118. try:
  119. other_target = target.get_previous_sibling()
  120. except Category.DoesNotExist:
  121. other_target = None
  122. if other_target:
  123. Category.objects.move_node(target, other_target, 'left')
  124. Category.objects.clear_cache()
  125. message = _('Category "%(name)s" has been moved above "%(other)s".')
  126. targets_names = {'name': target.name, 'other': other_target.name}
  127. messages.success(request, message % targets_names)