Browse Source

viewmodels api cleanup

Rafał Pitoń 8 years ago
parent
commit
d387a0a97d

+ 9 - 0
misago/core/deprecations.py

@@ -0,0 +1,9 @@
+import warnings
+
+
+class RemovedInMisagoWarning(Warning):
+    pass
+
+
+def warn(message, category=RemovedInMisagoWarning, stacklevel=0):
+    warnings.warn(message, category, stacklevel + 3)

+ 17 - 0
misago/core/tests/test_deprecations.py

@@ -0,0 +1,17 @@
+import warnings
+
+from django.test import TestCase, override_settings
+from django.utils import six
+
+from ..deprecations import RemovedInMisagoWarning, warn
+
+
+class DeprecationsTests(TestCase):
+    def test_deprecations_warn(self):
+        """deprecation utility raises warning"""
+        with warnings.catch_warnings(record=True) as warning:
+            warn("test warning")
+
+            self.assertEqual(len(warning), 1)
+            self.assertEqual(six.text_type(warning[0].message), "test warning")
+            self.assertTrue(issubclass(warning[0].category, RemovedInMisagoWarning))

+ 6 - 0
misago/core/viewmodel.py

@@ -0,0 +1,6 @@
+class ViewModel(object):
+    def __getattr__(self, name):
+        return getattr(self._model, name)
+
+    def unwrap(self):
+        return self._model

+ 1 - 1
misago/threads/api/postendpoints/move.py

@@ -55,7 +55,7 @@ def clean_thread_for_move(request, thread, viewmodel):
         raise MoveError(_("Thread to move posts to is same as current one."))
 
     try:
-        new_thread = viewmodel(request, new_thread_id, select_for_update=True).model
+        new_thread = viewmodel(request, new_thread_id, select_for_update=True).unwrap()
     except PermissionDenied as e:
         raise MoveError(e.args[0])
     except Http404:

+ 1 - 1
misago/threads/api/threadendpoints/merge.py

@@ -36,7 +36,7 @@ def thread_merge_endpoint(request, thread, viewmodel):
         return Response({'detail': _("You can't merge thread with itself.")}, status=400)
 
     try:
-        other_thread = viewmodel(request, other_thread_id, select_for_update=True).model
+        other_thread = viewmodel(request, other_thread_id, select_for_update=True).unwrap()
         if not can_reply_thread(request.user, other_thread):
             raise PermissionDenied(_("You can't merge this thread into thread you can't reply."))
         if not other_thread.acl['can_merge']:

+ 1 - 1
misago/threads/api/threadpoll.py

@@ -24,7 +24,7 @@ class ViewSet(viewsets.ViewSet):
             request,
             get_int_or_404(thread_pk),
             select_for_update=select_for_update,
-        ).model
+        ).unwrap()
 
     def get_thread_for_update(self, request, thread_pk):
         return self.get_thread(request, thread_pk, select_for_update=True)

+ 21 - 21
misago/threads/api/threadposts.py

@@ -77,24 +77,24 @@ class ViewSet(viewsets.ViewSet):
     @list_route(methods=['post'])
     @transaction.atomic
     def merge(self, request, thread_pk):
-        thread = self.get_thread_for_update(request, thread_pk).model
+        thread = self.get_thread_for_update(request, thread_pk).unwrap()
         return posts_merge_endpoint(request, thread)
 
     @list_route(methods=['post'])
     @transaction.atomic
     def move(self, request, thread_pk):
-        thread = self.get_thread_for_update(request, thread_pk).model
+        thread = self.get_thread_for_update(request, thread_pk).unwrap()
         return posts_move_endpoint(request, thread, self.thread)
 
     @list_route(methods=['post'])
     @transaction.atomic
     def split(self, request, thread_pk):
-        thread = self.get_thread_for_update(request, thread_pk).model
+        thread = self.get_thread_for_update(request, thread_pk).unwrap()
         return posts_split_endpoint(request, thread)
 
     @transaction.atomic
     def create(self, request, thread_pk):
-        thread = self.get_thread_for_update(request, thread_pk).model
+        thread = self.get_thread_for_update(request, thread_pk).unwrap()
         allow_reply_thread(request.user, thread)
 
         post = Post(thread=thread, category=thread.category)
@@ -125,15 +125,15 @@ class ViewSet(viewsets.ViewSet):
 
     @transaction.atomic
     def update(self, request, thread_pk, pk):
-        thread = self.get_thread_for_update(request, thread_pk)
-        post = self.get_post_for_update(request, thread, pk).model
+        thread = self.get_thread_for_update(request, thread_pk).unwrap()
+        post = self.get_post_for_update(request, thread, pk).unwrap()
 
         allow_edit_post(request.user, post)
 
         posting = PostingEndpoint(
             request,
             PostingEndpoint.EDIT,
-            thread=thread.model,
+            thread=thread,
             post=post
         )
 
@@ -158,7 +158,7 @@ class ViewSet(viewsets.ViewSet):
     @transaction.atomic
     def partial_update(self, request, thread_pk, pk):
         thread = self.get_thread_for_update(request, thread_pk)
-        post = self.get_post_for_update(request, thread, pk).model
+        post = self.get_post_for_update(request, thread, pk).unwrap()
 
         if post.is_event:
             return event_patch_endpoint(request, post)
@@ -168,7 +168,7 @@ class ViewSet(viewsets.ViewSet):
     @transaction.atomic
     def delete(self, request, thread_pk, pk):
         thread = self.get_thread_for_update(request, thread_pk)
-        post = self.get_post_for_update(request, thread, pk).model
+        post = self.get_post_for_update(request, thread, pk).unwrap()
 
         if post.is_event:
             allow_delete_event(request.user, post)
@@ -177,8 +177,8 @@ class ViewSet(viewsets.ViewSet):
 
         moderation.delete_post(request.user, post)
 
-        thread.model.synchronize()
-        thread.model.save()
+        thread.synchronize()
+        thread.save()
 
         thread.category.synchronize()
         thread.category.save()
@@ -188,12 +188,12 @@ class ViewSet(viewsets.ViewSet):
     @detail_route(methods=['post'])
     @transaction.atomic
     def read(self, request, thread_pk, pk):
-        thread = self.get_thread(request, thread_pk)
-        post = self.get_post(request, thread, pk).model
+        thread = self.get_thread(request, thread_pk).unwrap()
+        post = self.get_post(request, thread, pk).unwrap()
 
         request.user.lock()
 
-        return post_read_endpoint(request, thread.model, post)
+        return post_read_endpoint(request, thread, post)
 
     @detail_route(methods=['get'], url_path='editor')
     def post_editor(self, request, thread_pk, pk):
@@ -203,7 +203,7 @@ class ViewSet(viewsets.ViewSet):
             read_aware=False,
             subscription_aware=False
         )
-        post = self.get_post(request, thread, pk).model
+        post = self.get_post(request, thread, pk).unwrap()
 
         allow_edit_post(request.user, post)
 
@@ -231,11 +231,11 @@ class ViewSet(viewsets.ViewSet):
             thread_pk,
             read_aware=False,
             subscription_aware=False
-        )
-        allow_reply_thread(request.user, thread.model)
+        ).unwrap()
+        allow_reply_thread(request.user, thread)
 
         if 'reply' in request.query_params:
-            reply_to = self.get_post(request, thread, request.query_params['reply']).model
+            reply_to = self.get_post(request, thread, request.query_params['reply']).unwrap()
 
             if reply_to.is_event:
                 raise PermissionDenied(_("You can't reply to events."))
@@ -254,14 +254,14 @@ class ViewSet(viewsets.ViewSet):
     def edits(self, request, thread_pk, pk):
         if request.method == 'GET':
             thread = self.get_thread(request, thread_pk)
-            post = self.get_post(request, thread, pk).model
+            post = self.get_post(request, thread, pk).unwrap()
 
             return get_edit_endpoint(request, post)
 
         if request.method == 'POST':
             with transaction.atomic():
                 thread = self.get_thread(request, thread_pk)
-                post = self.get_post_for_update(request, thread, pk).model
+                post = self.get_post_for_update(request, thread, pk).unwrap()
 
                 allow_edit_post(request.user, post)
 
@@ -270,7 +270,7 @@ class ViewSet(viewsets.ViewSet):
     @detail_route(methods=['get'])
     def likes(self, request, thread_pk, pk):
         thread = self.get_thread(request, thread_pk)
-        post = self.get_post(request, thread, pk).model
+        post = self.get_post(request, thread, pk).unwrap()
 
         if post.acl['can_see_likes'] < 2:
             raise PermissionDenied(_("You can't see who liked this post."))

+ 3 - 3
misago/threads/api/threads.py

@@ -49,12 +49,12 @@ class ViewSet(viewsets.ViewSet):
 
     @transaction.atomic
     def partial_update(self, request, pk):
-        thread = self.get_thread_for_update(request, pk).model
+        thread = self.get_thread_for_update(request, pk).unwrap()
         return thread_patch_endpoint(request, thread)
 
     @transaction.atomic
     def destroy(self, request, pk):
-        thread = self.get_thread_for_update(request, pk).model
+        thread = self.get_thread_for_update(request, pk)
 
         if thread.acl.get('can_hide') == 2:
             moderation.delete_thread(request.user, thread)
@@ -95,7 +95,7 @@ class ThreadViewSet(ViewSet):
     @detail_route(methods=['post'], url_path='merge')
     @transaction.atomic
     def thread_merge(self, request, pk):
-        thread = self.get_thread_for_update(request, pk).model
+        thread = self.get_thread_for_update(request, pk).unwrap()
         return thread_merge_endpoint(request, thread, self.thread)
 
     @list_route(methods=['post'], url_path='merge')

+ 2 - 5
misago/threads/viewmodels/category.py

@@ -4,10 +4,11 @@ from misago.acl import add_acl
 from misago.categories.models import Category
 from misago.categories.permissions import allow_browse_category, allow_see_category
 from misago.categories.serializers import BasicCategorySerializer
+from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.core.shortcuts import validate_slug
 
 
-class ViewModel(object):
+class ViewModel(BaseViewModel):
     def __init__(self, request, **kwargs):
         self._categories = self.get_categories(request)
         add_acl(request.user, self._categories)
@@ -17,10 +18,6 @@ class ViewModel(object):
         self._children = list(filter(lambda s: s.parent_id == self._model.pk, self._subcategories))
 
     @property
-    def model(self):
-        return self._model
-
-    @property
     def categories(self):
         return self._categories
 

+ 11 - 18
misago/threads/viewmodels/post.py

@@ -1,34 +1,26 @@
 from django.shortcuts import get_object_or_404
 
 from misago.acl import add_acl
+from misago.core.viewmodel import ViewModel as BaseViewModel
 
 from ..permissions.threads import exclude_invisible_posts
 
 
-class ViewModel(object):
+class ViewModel(BaseViewModel):
     def __init__(self, request, thread, pk, select_for_update=False):
         model = self.get_post(request, thread, pk, select_for_update)
 
         add_acl(request.user, model)
 
         self._model = model
-        self._thread = model.thread
-        self._category = model.category
-
-    @property
-    def model(self):
-        return self._model
-
-    @property
-    def thread(self):
-        return self._thread
-
-    @property
-    def category(self):
-        return self._category
 
     def get_post(self, request, thread, pk, select_for_update=False):
-        queryset = self.get_queryset(request, thread.model)
+        try:
+            thread_model = thread.unwrap()
+        except AttributeError:
+            thread_model = thread
+
+        queryset = self.get_queryset(request, thread_model)
         if select_for_update:
             queryset = queryset.select_for_update()
         else:
@@ -40,13 +32,14 @@ class ViewModel(object):
 
         post = get_object_or_404(queryset, pk=pk)
 
-        post.thread = thread.model
+        post.thread = thread_model
         post.category = thread.category
 
         return post
 
     def get_queryset(self, request, thread):
-        return exclude_invisible_posts(request.user, thread.category, thread.post_set)
+        return exclude_invisible_posts(
+            request.user, thread.category, thread.post_set)
 
 
 class ThreadPost(ViewModel):

+ 8 - 3
misago/threads/viewmodels/posts.py

@@ -12,7 +12,12 @@ from ..utils import add_likes_to_posts
 
 class ViewModel(object):
     def __init__(self, request, thread, page):
-        posts_queryset = self.get_queryset(request, thread.model)
+        try:
+            thread_model = thread.unwrap()
+        except AttributeError:
+            thread_model = thread
+
+        posts_queryset = self.get_queryset(request, thread_model)
 
         list_page = paginate(posts_queryset, page, settings.MISAGO_POSTS_PER_PAGE, settings.MISAGO_POSTS_TAIL)
         paginator = pagination_dict(list_page, include_page_range=False)
@@ -22,14 +27,14 @@ class ViewModel(object):
 
         for post in posts:
             post.category = thread.category
-            post.thread = thread.model
+            post.thread = thread_model
 
             if post.poster:
                 posters.append(post.poster)
 
         add_acl(request.user, posts)
 
-        make_posts_read_aware(request.user, thread.model, posts)
+        make_posts_read_aware(request.user, thread_model, posts)
         make_users_status_aware(request.user, posters)
 
         if thread.category.acl['can_see_posts_likes']:

+ 7 - 20
misago/threads/viewmodels/thread.py

@@ -4,6 +4,7 @@ from django.utils.translation import gettext as _
 from misago.acl import add_acl
 from misago.categories.models import THREADS_ROOT_NAME, Category
 from misago.core.shortcuts import validate_slug
+from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.readtracker.threadstracker import make_read_aware
 
 from ..models import Poll, Thread
@@ -23,9 +24,9 @@ BASE_RELATIONS = (
 )
 
 
-class ViewModel(object):
-    def __init__(self, request, pk, slug=None,
-            read_aware=False, subscription_aware=False, poll_votes_aware=False, select_for_update=False):
+class ViewModel(BaseViewModel):
+    def __init__(self, request, pk, slug=None, read_aware=False,
+            subscription_aware=False, poll_votes_aware=False, select_for_update=False):
         model = self.get_thread(request, pk, slug, select_for_update)
 
         model.path = self.get_thread_path(model.category)
@@ -39,8 +40,6 @@ class ViewModel(object):
             make_subscription_aware(request.user, model)
 
         self._model = model
-        self._category = model.category
-        self._path = model.path
 
         try:
             self._poll = model.poll
@@ -52,18 +51,6 @@ class ViewModel(object):
             self._poll = None
 
     @property
-    def model(self):
-        return self._model
-
-    @property
-    def category(self):
-        return self._category
-
-    @property
-    def path(self):
-        return self._path
-
-    @property
     def poll(self):
         return self._poll
 
@@ -96,15 +83,15 @@ class ViewModel(object):
         return {
             'thread': self._model,
             'poll': self._poll,
-            'category': self._category,
-            'breadcrumbs': self._path
+            'category': self._model.category,
+            'breadcrumbs': self._model.path
         }
 
 
 class ForumThread(ViewModel):
     def get_thread(self, request, pk, slug=None, select_for_update=False):
         if select_for_update:
-            queryset = Thread.objects.select_for_update().select_related('category')
+            queryset = Thread.objects.select_for_update()
         else:
             queryset = Thread.objects.select_related(*BASE_RELATIONS)
 

+ 6 - 4
misago/threads/viewmodels/threads.py

@@ -41,10 +41,12 @@ class ViewModel(object):
     def __init__(self, request, category, list_type, page):
         self.allow_see_list(request, category, list_type)
 
+        category_model = category.unwrap()
+
         base_queryset = self.get_base_queryset(request, category.categories, list_type)
-        threads_categories = [category.model] + category.subcategories
+        threads_categories = [category_model] + category.subcategories
 
-        threads_queryset = self.get_remaining_threads_queryset(base_queryset, category.model, threads_categories)
+        threads_queryset = self.get_remaining_threads_queryset(base_queryset, category_model, threads_categories)
 
         list_page = paginate(threads_queryset, page, settings.MISAGO_THREADS_PER_PAGE, settings.MISAGO_THREADS_TAIL)
         paginator = pagination_dict(list_page, include_page_range=False)
@@ -52,7 +54,7 @@ class ViewModel(object):
         if list_page.number > 1:
             threads = list(list_page.object_list)
         else:
-            pinned_threads = list(self.get_pinned_threads(base_queryset, category.model, threads_categories))
+            pinned_threads = list(self.get_pinned_threads(base_queryset, category_model, threads_categories))
             threads = list(pinned_threads) + list(list_page.object_list)
 
         if list_type in ('new', 'unread'):
@@ -61,7 +63,7 @@ class ViewModel(object):
         else:
             threadstracker.make_threads_read_aware(request.user, threads)
 
-        add_categories_to_threads(category.model, category.categories, threads)
+        add_categories_to_threads(category_model, category.categories, threads)
         add_acl(request.user, threads)
         make_subscription_aware(request.user, threads)
 

+ 1 - 1
misago/threads/views/goto.py

@@ -16,7 +16,7 @@ class GotoView(View):
     read_aware=False
 
     def get(self, request, pk, slug, **kwargs):
-        thread = self.get_thread(request, pk, slug).model
+        thread = self.get_thread(request, pk, slug).unwrap()
         self.test_permissions(request, thread)
 
         posts_queryset = exclude_invisible_posts(request.user, thread.category, thread.post_set)

+ 6 - 1
misago/threads/views/thread.py

@@ -23,7 +23,12 @@ class ThreadBase(View):
         return render(request, self.template_name, template_context)
 
     def get_thread(self, request, pk, slug):
-        return self.thread(request, pk, slug, read_aware=True, subscription_aware=True, poll_votes_aware=True)
+        return self.thread(
+            request, pk, slug,
+            read_aware=True,
+            subscription_aware=True,
+            poll_votes_aware=True
+        )
 
     def get_posts(self, request, thread, page):
         return self.posts(request, thread, page)