category.py 3.6 KB

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