X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/142cf364fb3fc7cd95df709126ada97b6944c128..e9cd7fc641895a7702a8f81fcd11c388dd7d9db7:/apps/catalogue/models.py diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index 3fd80ef8a..288a18906 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 @@ -24,7 +23,8 @@ from django.conf import settings 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.utils import create_zip, split_tags +from catalogue.tasks import touch_tag from shutil import copy from glob import glob import re @@ -61,7 +61,6 @@ class Tag(TagBase): category = models.CharField(_('category'), max_length=50, blank=False, null=False, db_index=True, choices=TAG_CATEGORIES) description = models.TextField(_('description'), blank=True) - main_page = models.BooleanField(_('main page'), default=False, db_index=True, help_text=_('Show tag on main page')) user = models.ForeignKey(User, blank=True, null=True) book_count = models.IntegerField(_('book count'), blank=True, null=True) @@ -106,25 +105,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): @@ -168,6 +164,35 @@ class Tag(TagBase): def url_chunk(self): return '/'.join((Tag.categories_dict[self.category], self.slug)) + @staticmethod + def tags_from_info(info): + from slughifi import slughifi + from sortify import sortify + meta_tags = [] + categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch')) + for field_name, category in categories: + try: + tag_names = getattr(info, field_name) + except: + try: + tag_names = [getattr(info, category)] + except: + # For instance, Pictures do not have 'genre' field. + continue + for tag_name in tag_names: + tag_sort_key = tag_name + if category == 'author': + tag_sort_key = tag_name.last_name + tag_name = tag_name.readable() + tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) + if created: + tag.name = tag_name + tag.sort_key = sortify(tag_sort_key.lower()) + tag.save() + meta_tags.append(tag) + return meta_tags + + def get_dynamic_path(media, filename, ext=None, maxlen=100): from slughifi import slughifi @@ -334,6 +359,8 @@ class Book(models.Model): wiki_link = models.CharField(blank=True, max_length=240) # files generated during publication + cover = models.FileField(_('cover'), upload_to=book_upload_path('png'), + null=True, blank=True) ebook_formats = ['pdf', 'epub', 'mobi', 'txt'] formats = ebook_formats + ['html', 'xml'] @@ -463,6 +490,7 @@ class Book(models.Model): cache_key = "Book.short_html/%d/%s" for lang, langname in settings.LANGUAGES: cache.delete(cache_key % (self.id, lang)) + cache.delete("Book.mini_box/%d" % (self.id, )) # Fragment.short_html relies on book's tags, so reset it here too for fragm in self.fragments.all(): fragm.reset_short_html() @@ -477,22 +505,17 @@ class Book(models.Model): if short_html is not None: return mark_safe(short_html) else: - tags = self.tags.filter(~Q(category__in=('set', 'theme', 'book'))) - tags = [mark_safe(u'%s' % (tag.get_absolute_url(), tag.name)) for tag in tags] + tags = self.tags.filter(category__in=('author', 'kind', 'genre', 'epoch')) + tags = split_tags(tags) formats = [] # files generated during publication - if self.has_media("html"): - formats.append(u'%s' % (reverse('book_text', args=[self.fileid()]), _('Read online'))) for ebook_format in self.ebook_formats: if self.has_media(ebook_format): formats.append(u'%s' % ( - self.get_media(ebook_format).url, + "", #self.get_media(ebook_format).url, ebook_format.upper() )) - # other files - for m in self.media.order_by('type'): - formats.append(u'%s' % (m.file.url, m.type.upper())) formats = [mark_safe(format) for format in formats] @@ -505,7 +528,7 @@ class Book(models.Model): def mini_box(self): if self.id: - cache_key = "Book.mini_boxs/%d" % (self.id, ) + cache_key = "Book.mini_box/%d" % (self.id, ) short_html = cache.get(cache_key) else: short_html = None @@ -549,6 +572,20 @@ class Book(models.Model): provider=ORMDocProvider(self), parse_dublincore=parse_dublincore) + def build_cover(self, book_info=None): + """(Re)builds the cover image.""" + from StringIO import StringIO + from django.core.files.base import ContentFile + from librarian.cover import WLCover + + if book_info is None: + book_info = self.wldocument().book_info + + cover = WLCover(book_info).image() + imgstr = StringIO() + cover.save(imgstr, 'png') + self.cover.save(None, ContentFile(imgstr.getvalue())) + def build_pdf(self, customizations=None, file_name=None): """ (Re)builds the pdf file. customizations - customizations which are passed to LaTeX class file. @@ -712,7 +749,6 @@ class Book(models.Model): def from_text_and_meta(cls, raw_file, book_info, overwrite=False, build_epub=True, build_txt=True, build_pdf=True, build_mobi=True): import re - from slughifi import slughifi from sortify import sortify # check for parts before we do anything @@ -747,24 +783,7 @@ class Book(models.Model): book.set_extra_info_value(book_info.to_dict()) book.save() - meta_tags = [] - categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch')) - for field_name, category in categories: - try: - tag_names = getattr(book_info, field_name) - except: - tag_names = [getattr(book_info, category)] - for tag_name in tag_names: - tag_sort_key = tag_name - if category == 'author': - tag_sort_key = tag_name.last_name - tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name - tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) - if created: - tag.name = tag_name - tag.sort_key = sortify(tag_sort_key.lower()) - tag.save() - meta_tags.append(tag) + meta_tags = Tag.tags_from_info(book_info) book.tags = set(meta_tags + book_shelves) @@ -785,6 +804,8 @@ class Book(models.Model): if not settings.NO_BUILD_TXT and build_txt: book.build_txt() + book.build_cover(book_info) + if not settings.NO_BUILD_EPUB and build_epub: book.build_epub() @@ -795,15 +816,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 @@ -1027,7 +1053,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 \