X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/87e084d47c335cd6f0b3e91d614999f55d148044..452c475a6450a61a15c857594f995315cf153083:/src/catalogue/helpers.py?ds=sidebyside diff --git a/src/catalogue/helpers.py b/src/catalogue/helpers.py index b48c483ea..c4b926783 100644 --- a/src/catalogue/helpers.py +++ b/src/catalogue/helpers.py @@ -1,22 +1,22 @@ -# -*- 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 django.conf import settings from django.contrib.contenttypes.models import ContentType -from django.db.models import Count +from django.core.cache import cache + from .models import Tag, Book from os.path import getmtime -import cPickle +import pickle from collections import defaultdict - BOOK_CATEGORIES = ('author', 'epoch', 'genre', 'kind') - _COUNTERS = None -_COUNTER_TIME = None +_COUNTER_TIME = 0 + + def get_top_level_related_tags(tags, categories=None): """ Finds tags related to given tags through books, and counts their usage. @@ -27,8 +27,17 @@ def get_top_level_related_tags(tags, categories=None): global _COUNTERS, _COUNTER_TIME # First, check that we have a valid and recent version of the counters. if getmtime(settings.CATALOGUE_COUNTERS_FILE) > _COUNTER_TIME: - with open(settings.CATALOGUE_COUNTERS_FILE) as f: - _COUNTERS = cPickle.load(f) + for i in range(10): + try: + with open(settings.CATALOGUE_COUNTERS_FILE, 'rb') as f: + _COUNTERS = pickle.load(f) + except (EOFError, ValueError): + if i < 9: + continue + else: + raise + else: + break tagids = tuple(sorted(t.pk for t in tags)) try: @@ -38,7 +47,6 @@ def get_top_level_related_tags(tags, categories=None): related = Tag.objects.filter(pk__in=related_ids) - # TODO: do we really need that? if categories is not None: related = related.filter(category__in=categories) @@ -46,8 +54,6 @@ def get_top_level_related_tags(tags, categories=None): tag.count = _COUNTERS['count'][tuple(sorted(tagids + (tag.pk,)))] yield tag - #~ return related - def update_counters(): def combinations(things): @@ -61,7 +67,7 @@ def update_counters(): def count_for_book(book, count_by_combination=None, parent_combinations=None): if not parent_combinations: parent_combinations = set() - tags = sorted(tuple(t.pk for t in book.tags.filter(category__in=('author', 'genre', 'epoch', 'kind')))) + tags = sorted(book.tags.filter(category__in=('author', 'genre', 'epoch', 'kind')).values_list('pk', flat=True)) combs = list(combinations(tags)) for c in combs: if c not in parent_combinations: @@ -71,7 +77,7 @@ def update_counters(): count_for_book(child, count_by_combination, combs_for_child) count_by_combination = defaultdict(lambda: 0) - for b in Book.objects.filter(parent=None): + for b in Book.objects.filter(findable=True, parent=None): count_for_book(b, count_by_combination) next_combinations = defaultdict(set) @@ -88,5 +94,18 @@ def update_counters(): "next": dict(next_combinations), } - with open(settings.CATALOGUE_COUNTERS_FILE, 'w') as f: - cPickle.dump(counters, f) + with open(settings.CATALOGUE_COUNTERS_FILE, 'wb') as f: + pickle.dump(counters, f) + + +def get_audiobook_tags(): + audiobook_tag_ids = cache.get('audiobook_tags') + if audiobook_tag_ids is None: + books_with_audiobook = Book.objects.filter(findable=True, media__type__in=('mp3', 'ogg'))\ + .distinct().values_list('pk', flat=True) + audiobook_tag_ids = Tag.objects.filter( + items__content_type=ContentType.objects.get_for_model(Book), + items__object_id__in=list(books_with_audiobook)).distinct().values_list('pk', flat=True) + audiobook_tag_ids = list(audiobook_tag_ids) + cache.set('audiobook_tags', audiobook_tag_ids) + return audiobook_tag_ids