From: Radek Czajka Date: Mon, 19 Dec 2011 14:37:01 +0000 (+0100) Subject: update Tag.book_count in celery X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/54e4ec4a3aac555f44ea604c12a3955592b5d568?ds=sidebyside update Tag.book_count in celery --- diff --git a/apps/api/handlers.py b/apps/api/handlers.py index e10a4b5a2..62708c953 100644 --- a/apps/api/handlers.py +++ b/apps/api/handlers.py @@ -249,9 +249,8 @@ class TagsHandler(BaseHandler): except KeyError, e: return rc.NOT_FOUND - tags = Tag.objects.filter(category=category_sng) - tags = [t for t in tags if t.get_count() > 0] - if tags: + tags = Tag.objects.filter(category=category_sng).exclude(book_count=0) + if tags.exists(): return tags else: return rc.NOT_FOUND @@ -518,7 +517,7 @@ class CatalogueHandler(BaseHandler): changed_at__gte=since, changed_at__lt=until): # only serve non-empty tags - if tag.get_count(): + if tag.book_count: tag_d = cls.tag_dict(tag, fields) updated.append(tag_d) elif tag.created_at < since: diff --git a/apps/api/management/commands/mobileinit.py b/apps/api/management/commands/mobileinit.py index 658b1770d..2abbfb3d3 100755 --- a/apps/api/management/commands/mobileinit.py +++ b/apps/api/management/commands/mobileinit.py @@ -23,10 +23,10 @@ class Command(BaseCommand): db = init_db(last_checked) for b in Book.objects.all(): add_book(db, b) - for t in Tag.objects.exclude(category__in=('book', 'set', 'theme')): + for t in Tag.objects.exclude( + category__in=('book', 'set', 'theme')).exclude(book_count=0): # only add non-empty tags - if t.get_count(): - add_tag(db, t) + add_tag(db, t) db.commit() db.close() current(last_checked) diff --git a/apps/catalogue/forms.py b/apps/catalogue/forms.py index 852513a57..9707e793d 100644 --- a/apps/catalogue/forms.py +++ b/apps/catalogue/forms.py @@ -56,7 +56,7 @@ class ObjectSetsForm(forms.Form): self.fields['set_ids'] = forms.MultipleChoiceField( label=_('Shelves'), required=False, - choices=[(tag.id, "%s (%s)" % (tag.name, tag.get_count())) for tag in Tag.objects.filter(category='set', user=user)], + choices=[(tag.id, "%s (%s)" % (tag.name, tag.book_count)) for tag in Tag.objects.filter(category='set', user=user)], initial=[tag.id for tag in obj.tags.filter(category='set', user=user)], widget=forms.CheckboxSelectMultiple ) diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index 2b33964c2..359a89e7e 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -3,7 +3,6 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from collections import namedtuple -from datetime import datetime from django.db import models from django.db.models import permalink, Q @@ -25,6 +24,7 @@ from newtagging.models import TagBase, tags_updated from newtagging import managers from catalogue.fields import JSONField, OverwritingFileField from catalogue.utils import create_zip +from catalogue.tasks import touch_tag from shutil import copy from glob import glob import re @@ -106,25 +106,22 @@ class Tag(TagBase): has_description.boolean = True def get_count(self): - """ returns global book count for book tags, fragment count for themes """ - - if self.book_count is None: - if self.category == 'book': - # never used - objects = Book.objects.none() - elif self.category == 'theme': - objects = Fragment.tagged.with_all((self,)) - else: - objects = Book.tagged.with_all((self,)).order_by() - if self.category != 'set': - # eliminate descendants - l_tags = Tag.objects.filter(slug__in=[book.book_tag_slug() for book in objects]) - descendants_keys = [book.pk for book in Book.tagged.with_any(l_tags)] - if descendants_keys: - objects = objects.exclude(pk__in=descendants_keys) - self.book_count = objects.count() - self.save() - return self.book_count + """Returns global book count for book tags, fragment count for themes.""" + + if self.category == 'book': + # never used + objects = Book.objects.none() + elif self.category == 'theme': + objects = Fragment.tagged.with_all((self,)) + else: + objects = Book.tagged.with_all((self,)).order_by() + if self.category != 'set': + # eliminate descendants + l_tags = Tag.objects.filter(slug__in=[book.book_tag_slug() for book in objects]) + descendants_keys = [book.pk for book in Book.tagged.with_any(l_tags)] + if descendants_keys: + objects = objects.exclude(pk__in=descendants_keys) + return objects.count() @staticmethod def get_tag_list(tags): @@ -802,15 +799,20 @@ class Book(models.Model): book.build_mobi() book_descendants = list(book.children.all()) + descendants_tags = set() # add l-tag to descendants and their fragments while len(book_descendants) > 0: child_book = book_descendants.pop(0) + descendants_tags.update(child_book.tags) child_book.tags = list(child_book.tags) + [book_tag] child_book.save() for fragment in child_book.fragments.all(): fragment.tags = set(list(fragment.tags) + [book_tag]) book_descendants += list(child_book.children.all()) + for tag in descendants_tags: + touch_tag.delay(tag) + book.save() # refresh cache @@ -1034,7 +1036,8 @@ class Fragment(models.Model): def _tags_updated_handler(sender, affected_tags, **kwargs): # reset tag global counter # we want Tag.changed_at updated for API to know the tag was touched - Tag.objects.filter(pk__in=[tag.pk for tag in affected_tags]).update(book_count=None, changed_at=datetime.now()) + for tag in affected_tags: + touch_tag.delay(tag) # if book tags changed, reset book tag counter if isinstance(sender, Book) and \ diff --git a/apps/catalogue/tasks.py b/apps/catalogue/tasks.py new file mode 100755 index 000000000..5566fe177 --- /dev/null +++ b/apps/catalogue/tasks.py @@ -0,0 +1,16 @@ +# -*- 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 datetime import datetime +from celery.task import task + + +@task +def touch_tag(tag): + update_dict = { + 'book_count': tag.get_count(), + 'changed_at': datetime.now(), + } + + type(tag).objects.filter(pk=tag.pk).update(**update_dict) diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index e6e5eb927..902907db9 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -29,6 +29,7 @@ from django.views.generic.list_detail import object_list from catalogue import models from catalogue import forms from catalogue.utils import split_tags, AttachmentHttpResponse, async_build_pdf +from catalogue.tasks import touch_tag from pdcounter import models as pdcounter_models from pdcounter import views as pdcounter_views from suggest.forms import PublishingSuggestForm @@ -56,9 +57,11 @@ class JSONResponse(HttpResponse): def catalogue(request): - tags = models.Tag.objects.exclude(category__in=('set', 'book')) + tags = models.Tag.objects.exclude( + category__in=('set', 'book')).exclude(book_count=0) + tags = list(tags) for tag in tags: - tag.count = tag.get_count() + tag.count = tag.book_count categories = split_tags(tags) fragment_tags = categories.get('theme', []) @@ -520,12 +523,10 @@ def book_sets(request, book): new_shelves = [models.Tag.objects.get(pk=id) for id in form.cleaned_data['set_ids']] for shelf in [shelf for shelf in old_shelves if shelf not in new_shelves]: - shelf.book_count = None - shelf.save() + touch_tag(shelf) for shelf in [shelf for shelf in new_shelves if shelf not in old_shelves]: - shelf.book_count = None - shelf.save() + touch_tag(shelf) book.tags = new_shelves + list(book.tags.filter(~Q(category='set') | ~Q(user=request.user))) if request.is_ajax(): @@ -553,9 +554,7 @@ def remove_from_shelf(request, shelf, book): if shelf in book.tags: models.Tag.objects.remove_tag(book, shelf) - - shelf.book_count = None - shelf.save() + touch_tag(shelf) return HttpResponse(_('Book was successfully removed from the shelf')) else: diff --git a/apps/opds/views.py b/apps/opds/views.py index c7d38284b..06e011963 100644 --- a/apps/opds/views.py +++ b/apps/opds/views.py @@ -229,7 +229,7 @@ class ByCategoryFeed(Feed): return feed['title'] def items(self, feed): - return (tag for tag in Tag.objects.filter(category=feed['category']) if tag.get_count() > 0) + return Tag.objects.filter(category=feed['category']).exclude(book_count=0) def item_title(self, item): return item.name @@ -280,7 +280,7 @@ class UserFeed(Feed): return u"Półki użytkownika %s" % user.username def items(self, user): - return (tag for tag in Tag.objects.filter(category='set', user=user) if tag.get_count() > 0) + return Tag.objects.filter(category='set', user=user).exclude(book_count=0) def item_title(self, item): return item.name diff --git a/wolnelektury/templates/catalogue/tag_list.html b/wolnelektury/templates/catalogue/tag_list.html index e96320e90..3f842acc7 100644 --- a/wolnelektury/templates/catalogue/tag_list.html +++ b/wolnelektury/templates/catalogue/tag_list.html @@ -5,7 +5,7 @@ {% else %} {% endif %} diff --git a/wolnelektury/templates/catalogue/user_shelves.html b/wolnelektury/templates/catalogue/user_shelves.html index d047dbe74..28c122295 100644 --- a/wolnelektury/templates/catalogue/user_shelves.html +++ b/wolnelektury/templates/catalogue/user_shelves.html @@ -3,7 +3,7 @@ {% if shelves %} {% else %}