thread.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 = ('category', 'starter', 'starter__rank', 'starter__ban_cache', 'starter__online_tracker')
  13. class ViewModel(object):
  14. def __init__(self, request, pk, slug=None, read_aware=False, subscription_aware=False, select_for_update=False):
  15. model = self.get_thread(request, pk, slug, select_for_update)
  16. model.path = self.get_thread_path(model.category)
  17. add_acl(request.user, model.category)
  18. add_acl(request.user, model)
  19. if read_aware:
  20. make_read_aware(request.user, model)
  21. if subscription_aware:
  22. make_subscription_aware(request.user, model)
  23. self._model = model
  24. self._category = model.category
  25. self._path = model.path
  26. @property
  27. def model(self):
  28. return self._model
  29. @property
  30. def category(self):
  31. return self._category
  32. @property
  33. def path(self):
  34. return self._path
  35. def get_thread(self, request, pk, slug=None, select_for_update=False):
  36. raise NotImplementedError('Thread view model has to implement get_thread(request, pk, slug=None)')
  37. def get_thread_path(self, category):
  38. thread_path = []
  39. if category.level:
  40. categories = Category.objects.filter(
  41. tree_id=category.tree_id,
  42. lft__lte=category.lft,
  43. rght__gte=category.rght
  44. ).order_by('level')
  45. thread_path = list(categories)
  46. else:
  47. thread_path = [category]
  48. thread_path[0].name = self.get_root_name()
  49. return thread_path
  50. def get_root_name(self):
  51. raise NotImplementedError('Thread view model has to implement get_root_name()')
  52. def get_frontend_context(self):
  53. return ThreadSerializer(self._model).data
  54. def get_template_context(self):
  55. return {
  56. 'thread': self._model,
  57. 'category': self._category,
  58. 'breadcrumbs': self._path
  59. }
  60. class ForumThread(ViewModel):
  61. def get_thread(self, request, pk, slug=None, select_for_update=False):
  62. if select_for_update:
  63. queryset = Thread.objects.select_for_update().select_related('category')
  64. else:
  65. queryset = Thread.objects.select_related(*BASE_RELATIONS)
  66. thread = get_object_or_404(
  67. queryset,
  68. pk=pk,
  69. category__tree_id=trees_map.get_tree_id_for_root(THREADS_ROOT_NAME)
  70. )
  71. allow_see_thread(request.user, thread)
  72. if slug:
  73. validate_slug(thread, slug)
  74. return thread
  75. def get_root_name(self):
  76. return _("Threads")