base.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from django.http import Http404
  2. from django.shortcuts import render
  3. from django.views.generic import View
  4. from misago.acl import add_acl
  5. from misago.core.shortcuts import get_object_or_404, validate_slug
  6. from misago.forums.models import Forum
  7. from misago.forums.permissions import allow_see_forum, allow_browse_forum
  8. from misago.threads.models import Thread, Post
  9. from misago.threads.permissions import (allow_see_thread, allow_see_post,
  10. exclude_invisible_posts)
  11. __all__ = ['ForumMixin', 'ThreadMixin', 'PostMixin', 'ViewBase']
  12. class ForumMixin(object):
  13. """
  14. Mixin for getting forums
  15. """
  16. def get_forum(self, request, lock=False, **kwargs):
  17. forum = self.fetch_forum(request, lock, **kwargs)
  18. self.check_forum_permissions(request, forum)
  19. if kwargs.get('forum_slug'):
  20. validate_slug(forum, kwargs.get('forum_slug'))
  21. return forum
  22. def fetch_forum(self, request, lock=False, **kwargs):
  23. queryset = Forum.objects
  24. if lock:
  25. queryset = queryset.select_for_update()
  26. return get_object_or_404(
  27. queryset, id=kwargs.get('forum_id'), role='forum')
  28. def check_forum_permissions(self, request, forum):
  29. if forum.special_role:
  30. raise Http404()
  31. add_acl(request.user, forum)
  32. allow_see_forum(request.user, forum)
  33. allow_browse_forum(request.user, forum)
  34. class ThreadMixin(object):
  35. """
  36. Mixin for getting thread
  37. """
  38. def get_thread(self, request, lock=False, **kwargs):
  39. thread = self.fetch_thread(request, lock, **kwargs)
  40. self.check_thread_permissions(request, thread)
  41. if kwargs.get('thread_slug'):
  42. validate_slug(thread, kwargs.get('thread_slug'))
  43. return thread
  44. def fetch_thread(self, request, lock=False, select_related=None,
  45. queryset=None, **kwargs):
  46. queryset = queryset or Thread.objects
  47. if lock:
  48. queryset = queryset.select_for_update()
  49. select_related = select_related or []
  50. if not 'forum' in select_related:
  51. select_related.append('forum')
  52. queryset = queryset.select_related(*select_related)
  53. where = {'id': kwargs.get('thread_id')}
  54. if 'forum_id' in kwargs:
  55. where['forum_id'] = kwargs.get('forum_id')
  56. return get_object_or_404(queryset, **where)
  57. def check_thread_permissions(self, request, thread):
  58. if thread.forum.special_role:
  59. raise Http404()
  60. add_acl(request.user, thread.forum)
  61. add_acl(request.user, thread)
  62. allow_see_thread(request.user, thread)
  63. allow_see_forum(request.user, thread.forum)
  64. class PostMixin(object):
  65. def get_post(self, request, lock=False, **kwargs):
  66. post = self.fetch_post(request, lock, **kwargs)
  67. post.thread.forum = post.forum
  68. self.check_post_permissions(request, post)
  69. return post
  70. def fetch_post(self, request, lock=False, select_related=None,
  71. queryset=None, **kwargs):
  72. queryset = queryset or Post.objects
  73. if lock:
  74. queryset = queryset.select_for_update()
  75. select_related = select_related or []
  76. if not 'forum' in select_related:
  77. select_related.append('forum')
  78. if not 'thread' in select_related:
  79. select_related.append('thread')
  80. queryset = queryset.select_related(*select_related)
  81. where = {'id': kwargs.get('post_id')}
  82. if 'thread_id' in kwargs:
  83. where['thread_id'] = kwargs.get('thread_id')
  84. if 'forum_id' in kwargs:
  85. where['forum_id'] = kwargs.get('forum_id')
  86. return get_object_or_404(queryset, **where)
  87. def check_post_permissions(self, request, post):
  88. if post.forum.special_role:
  89. raise Http404()
  90. add_acl(request.user, post.forum)
  91. add_acl(request.user, post.thread)
  92. add_acl(request.user, post)
  93. allow_see_post(request.user, post)
  94. allow_see_thread(request.user, post.thread)
  95. allow_see_forum(request.user, post.forum)
  96. def exclude_invisible_posts(self, queryset, user, forum, thread):
  97. return exclude_invisible_posts(queryset, user, forum)
  98. class ViewBase(ForumMixin, ThreadMixin, PostMixin, View):
  99. def process_context(self, request, context):
  100. """
  101. Simple hook for extending and manipulating template context.
  102. """
  103. return context
  104. def render(self, request, context=None, template=None):
  105. context = self.process_context(request, context or {})
  106. template = template or self.template
  107. return render(request, template, context)