Support longer tag names.
[wolnelektury.git] / apps / social / utils.py
index 96f0ca0..bf1c242 100755 (executable)
@@ -1,11 +1,45 @@
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from collections import defaultdict
+from django.contrib.contenttypes.models import ContentType
 from django.db.models import Q
-from catalogue.models import Tag
+from django.utils.functional import lazy
+from catalogue.models import Book, Tag
 from catalogue import utils
 from catalogue.tasks import touch_tag
+from social.models import Cite
 
 
-def likes(user, work):
-    return user.is_authenticated() and work.tags.filter(category='set', user=user).exists()
+def likes(user, work, request=None):
+    if not user.is_authenticated():
+        return False
+
+    if request is None:
+        return work.tags.filter(category='set', user=user).exists()
+
+    if not hasattr(request, 'social_likes'):
+        # tuple: unchecked, checked, liked
+        request.social_likes = defaultdict(lambda:(set(), set(), set()))
+
+    ct = ContentType.objects.get_for_model(type(work))
+    likes_t = request.social_likes[ct.pk]
+    if work.pk in likes_t[1]:
+        return work.pk in likes_t[2]
+    else:
+        likes_t[0].add(work.pk)
+        def _likes():
+            if likes_t[0]:
+                ids = tuple(likes_t[0])
+                likes_t[0].clear()
+                likes_t[2].update(Tag.intermediary_table_model.objects.filter(
+                    content_type_id=ct.pk, tag__user_id=user.pk,
+                    object_id__in=ids
+                ).distinct().values_list('object_id', flat=True))
+                likes_t[1].update(ids)
+            return work.pk in likes_t[2]
+        return lazy(_likes, bool)()
 
 
 def get_set(user, name):
@@ -32,4 +66,9 @@ def set_sets(user, work, sets):
         touch_tag(shelf)
 
     # delete empty tags
-    Tag.objects.filter(category='set', user=user, book_count=0).delete()
+    Tag.objects.filter(category='set', user=user, items=None).delete()
+
+
+def cites_for_tags(tags):
+    """Returns a QuerySet with all Cites for books with given tags."""
+    return Cite.objects.filter(book__in=Book.tagged.with_all(tags))