thread.py 2.8 KB

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