thread.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. from django.shortcuts import get_object_or_404
  2. from django.utils.translation import gettext as _
  3. from misago.acl import add_acl
  4. from misago.categories.models import THREADS_ROOT_NAME, Category
  5. from misago.core.shortcuts import validate_slug
  6. from misago.readtracker.threadstracker import make_read_aware
  7. from ..models import Thread
  8. from ..permissions.threads import allow_see_thread
  9. from ..serializers import ThreadSerializer
  10. from ..subscriptions import make_subscription_aware
  11. from ..threadtypes import trees_map
  12. BASE_RELATIONS = (
  13. 'category',
  14. 'poll',
  15. 'starter',
  16. 'starter__rank',
  17. 'starter__ban_cache',
  18. 'starter__online_tracker'
  19. )
  20. class ViewModel(object):
  21. def __init__(self, request, pk, slug=None, read_aware=False, subscription_aware=False, select_for_update=False):
  22. model = self.get_thread(request, pk, slug, select_for_update)
  23. model.path = self.get_thread_path(model.category)
  24. add_acl(request.user, model.category)
  25. add_acl(request.user, model)
  26. if read_aware:
  27. make_read_aware(request.user, model)
  28. if subscription_aware:
  29. make_subscription_aware(request.user, model)
  30. self._model = model
  31. self._category = model.category
  32. self._path = model.path
  33. @property
  34. def model(self):
  35. return self._model
  36. @property
  37. def category(self):
  38. return self._category
  39. @property
  40. def path(self):
  41. return self._path
  42. def get_thread(self, request, pk, slug=None, select_for_update=False):
  43. raise NotImplementedError('Thread view model has to implement get_thread(request, pk, slug=None)')
  44. def get_thread_path(self, category):
  45. thread_path = []
  46. if category.level:
  47. categories = Category.objects.filter(
  48. tree_id=category.tree_id,
  49. lft__lte=category.lft,
  50. rght__gte=category.rght
  51. ).order_by('level')
  52. thread_path = list(categories)
  53. else:
  54. thread_path = [category]
  55. thread_path[0].name = self.get_root_name()
  56. return thread_path
  57. def get_root_name(self):
  58. raise NotImplementedError('Thread view model has to implement get_root_name()')
  59. def get_frontend_context(self):
  60. return ThreadSerializer(self._model).data
  61. def get_template_context(self):
  62. return {
  63. 'thread': self._model,
  64. 'category': self._category,
  65. 'breadcrumbs': self._path
  66. }
  67. class ForumThread(ViewModel):
  68. def get_thread(self, request, pk, slug=None, select_for_update=False):
  69. if select_for_update:
  70. queryset = Thread.objects.select_for_update().select_related('category')
  71. else:
  72. queryset = Thread.objects.select_related(*BASE_RELATIONS)
  73. thread = get_object_or_404(
  74. queryset,
  75. pk=pk,
  76. category__tree_id=trees_map.get_tree_id_for_root(THREADS_ROOT_NAME)
  77. )
  78. allow_see_thread(request.user, thread)
  79. if slug:
  80. validate_slug(thread, slug)
  81. return thread
  82. def get_root_name(self):
  83. return _("Threads")