category.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from django.http import Http404
  2. from misago.acl.objectacl import add_acl_to_obj
  3. from misago.categories.models import Category
  4. from misago.categories.permissions import allow_browse_category, allow_see_category
  5. from misago.categories.serializers import CategorySerializer
  6. from misago.core.shortcuts import validate_slug
  7. from misago.core.viewmodel import ViewModel as BaseViewModel
  8. from misago.threads.permissions import allow_use_private_threads
  9. __all__ = ["ThreadsRootCategory", "ThreadsCategory", "PrivateThreadsCategory"]
  10. class ViewModel(BaseViewModel):
  11. def __init__(self, request, **kwargs):
  12. self._categories = self.get_categories(request)
  13. add_acl_to_obj(request.user_acl, self._categories)
  14. self._model = self.get_category(request, self._categories, **kwargs)
  15. self._subcategories = list(filter(self._model.has_child, self._categories))
  16. self._children = list(
  17. filter(lambda s: s.parent_id == self._model.pk, self._subcategories)
  18. )
  19. @property
  20. def categories(self):
  21. return self._categories
  22. @property
  23. def subcategories(self):
  24. return self._subcategories
  25. @property
  26. def children(self):
  27. return self._children
  28. def get_categories(self, request):
  29. raise NotImplementedError(
  30. "Category view model has to implement get_categories(request)"
  31. )
  32. def get_category(self, request, categories, **kwargs):
  33. return categories[0]
  34. def get_frontend_context(self):
  35. return {"CATEGORIES": BasicCategorySerializer(self._categories, many=True).data}
  36. def get_template_context(self):
  37. return {"category": self._model, "subcategories": self._children}
  38. class ThreadsRootCategory(ViewModel):
  39. def get_categories(self, request):
  40. return [Category.objects.root_category()] + list(
  41. Category.objects.all_categories()
  42. .filter(id__in=request.user_acl["visible_categories"])
  43. .select_related("parent")
  44. )
  45. class ThreadsCategory(ThreadsRootCategory):
  46. @property
  47. def level(self):
  48. return self._model.level
  49. def get_category(self, request, categories, **kwargs):
  50. for category in categories:
  51. if category.pk == int(kwargs["pk"]):
  52. if not category.special_role:
  53. # check permissions for non-special categories
  54. allow_see_category(request.user_acl, category)
  55. allow_browse_category(request.user_acl, category)
  56. if "slug" in kwargs:
  57. validate_slug(category, kwargs["slug"])
  58. return category
  59. raise Http404()
  60. class PrivateThreadsCategory(ViewModel):
  61. def get_categories(self, request):
  62. return [Category.objects.private_threads()]
  63. def get_category(self, request, categories, **kwargs):
  64. allow_use_private_threads(request.user_acl)
  65. return categories[0]
  66. BasicCategorySerializer = CategorySerializer.subset_fields(
  67. "id",
  68. "parent",
  69. "name",
  70. "description",
  71. "is_closed",
  72. "css_class",
  73. "level",
  74. "lft",
  75. "rght",
  76. "is_read",
  77. "url",
  78. )