Browse Source

backend for posts likes

Rafał Pitoń 8 years ago
parent
commit
dac17f197c

+ 10 - 0
misago/threads/serializers/post.py

@@ -23,6 +23,7 @@ class PostSerializer(serializers.ModelSerializer):
     acl = serializers.SerializerMethodField()
     acl = serializers.SerializerMethodField()
     is_read = serializers.SerializerMethodField()
     is_read = serializers.SerializerMethodField()
     is_new = serializers.SerializerMethodField()
     is_new = serializers.SerializerMethodField()
+    is_liked = serializers.SerializerMethodField()
 
 
     api = serializers.SerializerMethodField()
     api = serializers.SerializerMethodField()
     url = serializers.SerializerMethodField()
     url = serializers.SerializerMethodField()
@@ -52,8 +53,11 @@ class PostSerializer(serializers.ModelSerializer):
             'is_event',
             'is_event',
             'event_type',
             'event_type',
             'event_context',
             'event_context',
+            'likes',
+            'last_likes',
 
 
             'acl',
             'acl',
+            'is_liked',
             'is_new',
             'is_new',
             'is_read',
             'is_read',
 
 
@@ -82,6 +86,12 @@ class PostSerializer(serializers.ModelSerializer):
         except AttributeError:
         except AttributeError:
             return None
             return None
 
 
+    def get_is_liked(self, obj):
+        try:
+            return obj.is_liked
+        except AttributeError:
+            return None
+
     def get_is_new(self, obj):
     def get_is_new(self, obj):
         try:
         try:
             return obj.is_new
             return obj.is_new

+ 2 - 2
misago/threads/tests/test_thread_postlikes_api.py

@@ -42,8 +42,8 @@ class ThreadPostLikesApiTestCase(ThreadsApiTestCase):
 
 
     def test_likes(self):
     def test_likes(self):
         """api returns list of likes"""
         """api returns list of likes"""
-        like = testutils.like_post(self.user, self.post)
-        other_like = testutils.like_post(self.user, self.post)
+        like = testutils.like_post(self.post, self.user)
+        other_like = testutils.like_post(self.post, self.user)
 
 
         other_like.user = None
         other_like.user = None
         other_like.save()
         other_like.save()

+ 2 - 2
misago/threads/tests/test_thread_postpatch_api.py

@@ -668,7 +668,7 @@ class PostLikeApiTests(ThreadPostPatchApiTestCase):
 
 
     def test_unlike_post(self):
     def test_unlike_post(self):
         """api removes user like from post"""
         """api removes user like from post"""
-        testutils.like_post(self.user, self.post)
+        testutils.like_post(self.post, self.user)
 
 
         response = self.patch(self.api_link, [
         response = self.patch(self.api_link, [
             {'op': 'replace', 'path': 'is-liked', 'value': False}
             {'op': 'replace', 'path': 'is-liked', 'value': False}
@@ -686,7 +686,7 @@ class PostLikeApiTests(ThreadPostPatchApiTestCase):
 
 
     def test_like_post_no_change(self):
     def test_like_post_no_change(self):
         """api does no state change if we are linking liked post"""
         """api does no state change if we are linking liked post"""
-        testutils.like_post(self.user, self.post)
+        testutils.like_post(self.post, self.user)
 
 
         response = self.patch(self.api_link, [
         response = self.patch(self.api_link, [
             {'op': 'replace', 'path': 'is-liked', 'value': True}
             {'op': 'replace', 'path': 'is-liked', 'value': True}

+ 24 - 0
misago/threads/tests/test_threadview.py

@@ -430,3 +430,27 @@ class ThreadPollViewTests(ThreadViewTestCase):
         self.assertContains(response, poll.question)
         self.assertContains(response, poll.question)
         self.assertContains(response, '4 votes')
         self.assertContains(response, '4 votes')
         self.assertNotContains(response, 'Save your vote')
         self.assertNotContains(response, 'Save your vote')
+
+
+class ThreadLikedPostsViewTests(ThreadViewTestCase):
+    def test_liked_posts_display(self):
+        """view has no showstoppers on displaying posts with likes"""
+        testutils.like_post(self.thread.first_post, self.user)
+
+        response = self.client.get(self.thread.get_absolute_url())
+        self.assertContains(response, '"is_liked": true')
+
+    def test_liked_posts_no_permission(self):
+        """
+        view has no showstoppers on displaying posts with likes without perm
+        """
+        testutils.like_post(self.thread.first_post, self.user)
+
+        self.override_acl({
+            'can_see_posts_likes': 0
+        })
+
+        response = self.client.get(self.thread.get_absolute_url())
+        self.assertNotContains(response, '"is_liked": true')
+        self.assertNotContains(response, '"is_liked": false')
+        self.assertContains(response, '"is_liked": null')

+ 1 - 1
misago/threads/testutils.py

@@ -183,7 +183,7 @@ def post_poll(thread, poster):
     return poll
     return poll
 
 
 
 
-def like_post(user, post):
+def like_post(post, user):
     like = post.postlike_set.create(
     like = post.postlike_set.create(
         category=post.category,
         category=post.category,
         thread=post.thread,
         thread=post.thread,

+ 18 - 0
misago/threads/utils.py

@@ -2,6 +2,8 @@ from django.core.urlresolvers import resolve
 from django.utils import six
 from django.utils import six
 from django.utils.six.moves.urllib.parse import urlparse
 from django.utils.six.moves.urllib.parse import urlparse
 
 
+from .models import PostLike
+
 
 
 def add_categories_to_threads(root_category, categories, threads):
 def add_categories_to_threads(root_category, categories, threads):
     categories_dict = {}
     categories_dict = {}
@@ -37,6 +39,22 @@ def add_categories_to_threads(root_category, categories, threads):
                     thread.top_category = category
                     thread.top_category = category
 
 
 
 
+def add_likes_to_posts(user, posts):
+    if user.is_anonymous():
+        return
+
+    posts_map = {}
+    for post in posts:
+        posts_map[post.id] = post
+        post.is_liked = False
+
+    queryset = PostLike.objects.filter(
+        user=user, post_id__in=posts_map.keys())
+
+    for like in queryset.values('post_id'):
+        posts_map[like['post_id']].is_liked = True
+
+
 SUPPORTED_THREAD_ROUTES = {
 SUPPORTED_THREAD_ROUTES = {
     'misago:thread': 'pk',
     'misago:thread': 'pk',
     'misago:thread-post': 'pk',
     'misago:thread-post': 'pk',

+ 4 - 0
misago/threads/viewmodels/posts.py

@@ -7,6 +7,7 @@ from misago.users.online.utils import make_users_status_aware
 
 
 from ..permissions.threads import exclude_invisible_posts
 from ..permissions.threads import exclude_invisible_posts
 from ..serializers import PostSerializer
 from ..serializers import PostSerializer
+from ..utils import add_likes_to_posts
 
 
 
 
 class ViewModel(object):
 class ViewModel(object):
@@ -31,6 +32,9 @@ class ViewModel(object):
         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)
         make_users_status_aware(request.user, posters)
 
 
+        if thread.category.acl['can_see_posts_likes']:
+            add_likes_to_posts(request.user, posts)
+
         self._user = request.user
         self._user = request.user
 
 
         self.posts = posts
         self.posts = posts