X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/c6db46d42f0a6b9dbd5abb6ce2be58fe306752b6..a1edf3f1a7cff6e6f4d85a4288ca9b1d5cd3b254:/apps/catalogue/models/book.py diff --git a/apps/catalogue/models/book.py b/apps/catalogue/models/book.py index ea85645fa..f85cfceca 100644 --- a/apps/catalogue/models/book.py +++ b/apps/catalogue/models/book.py @@ -3,7 +3,7 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # import re -from django.conf import settings as settings +from django.conf import settings from django.core.cache import get_cache from django.db import models from django.db.models import permalink @@ -14,7 +14,7 @@ import jsonfield from catalogue import constants from catalogue.fields import EbookField from catalogue.models import Tag, Fragment, BookMedia -from catalogue.utils import create_zip, split_tags, book_upload_path +from catalogue.utils import create_zip, split_tags, book_upload_path, related_tag_name from catalogue import app_settings from catalogue import tasks from newtagging import managers @@ -27,6 +27,7 @@ class Book(models.Model): """Represents a book imported from WL-XML.""" title = models.CharField(_('title'), max_length=120) sort_key = models.CharField(_('sort key'), max_length=120, db_index=True, editable=False) + sort_key_author = models.CharField(_('sort key by author'), max_length=120, db_index=True, editable=False, default=u'') slug = models.SlugField(_('slug'), max_length=120, db_index=True, unique=True) common_slug = models.SlugField(_('slug'), max_length=120, db_index=True) @@ -36,13 +37,16 @@ class Book(models.Model): created_at = models.DateTimeField(_('creation date'), auto_now_add=True, db_index=True) changed_at = models.DateTimeField(_('creation date'), auto_now=True, db_index=True) parent_number = models.IntegerField(_('parent number'), default=0) - extra_info = jsonfield.JSONField(_('extra information'), default='{}') + extra_info = jsonfield.JSONField(_('extra information'), default={}) gazeta_link = models.CharField(blank=True, max_length=240) wiki_link = models.CharField(blank=True, max_length=240) # files generated during publication cover = EbookField('cover', _('cover'), upload_to=book_upload_path('jpg'), null=True, blank=True) + # Cleaner version of cover for thumbs + cover_thumb = EbookField('cover_thumb', _('cover thumbnail'), + upload_to=book_upload_path('th.jpg'), null=True, blank=True) ebook_formats = constants.EBOOK_FORMATS formats = ebook_formats + ['html', 'xml'] @@ -74,8 +78,9 @@ class Book(models.Model): from sortify import sortify self.sort_key = sortify(self.title) + self.title = unicode(self.title) # ??? - ret = super(Book, self).save(force_insert, force_update) + ret = super(Book, self).save(force_insert, force_update, **kwargs) if reset_short_html: self.reset_short_html() @@ -95,6 +100,12 @@ class Book(models.Model): def name(self): return self.title + def language_code(self): + return constants.LANGUAGES_3TO2.get(self.language, self.language) + + def language_name(self): + return dict(settings.LANGUAGES).get(self.language_code(), "") + def book_tag_slug(self): return ('l-' + self.slug)[:120] @@ -140,6 +151,14 @@ class Book(models.Model): for fragm in self.fragments.all().iterator(): fragm.reset_short_html() + try: + author = self.tags.filter(category='author')[0].sort_key + except IndexError: + author = u'' + type(self).objects.filter(pk=self.pk).update(sort_key_author=author) + + + def has_description(self): return len(self.description) > 0 has_description.short_description = _('description') @@ -194,20 +213,20 @@ class Book(models.Model): paths = map(lambda bm: (None, bm.file.path), bm) return create_zip(paths, "%s_%s" % (self.slug, format_)) - def search_index(self, book_info=None, reuse_index=False, index_tags=True): + def search_index(self, book_info=None, index=None, index_tags=True, commit=True): import search - if reuse_index: - idx = search.ReusableIndex() - else: - idx = search.Index() - - idx.open() + if index is None: + index = search.Index() try: - idx.index_book(self, book_info) + index.index_book(self, book_info) if index_tags: - idx.index_tags() - finally: - idx.close() + index.index_tags() + if commit: + index.index.commit() + except Exception, e: + index.index.rollback() + raise e + @classmethod def from_xml_file(cls, xml_file, **kwargs): @@ -228,7 +247,7 @@ class Book(models.Model): @classmethod def from_text_and_meta(cls, raw_file, book_info, overwrite=False, dont_build=None, search_index=True, - search_index_tags=True, search_index_reuse=False): + search_index_tags=True): if dont_build is None: dont_build = set() dont_build = set.union(set(dont_build), set(app_settings.DONT_BUILD)) @@ -303,6 +322,7 @@ class Book(models.Model): tasks.fix_tree_tags.delay(book) if 'cover' not in dont_build: book.cover.build_delay() + book.cover_thumb.build_delay() # No saves behind this point. @@ -315,8 +335,7 @@ class Book(models.Model): getattr(book, '%s_file' % format_).build_delay() if not settings.NO_SEARCH_INDEX and search_index: - book.search_index(index_tags=search_index_tags, reuse_index=search_index_reuse) - #index_book.delay(book.id, book_info) + tasks.index_book.delay(book.id, book_info=book_info, index_tags=search_index_tags) for child in notify_cover_changed: child.parent_cover_changed() @@ -386,12 +405,17 @@ class Book(models.Model): if not self.cover_info(inherit=False): if 'cover' not in app_settings.DONT_BUILD: self.cover.build_delay() + self.cover_thumb.build_delay() for format_ in constants.EBOOK_FORMATS_WITH_COVERS: if format_ not in app_settings.DONT_BUILD: getattr(self, '%s_file' % format_).build_delay() for child in self.children.all(): child.parent_cover_changed() + def other_versions(self): + """Find other versions (i.e. in other languages) of the book.""" + return type(self).objects.filter(common_slug=self.common_slug).exclude(pk=self.pk) + def related_info(self): """Keeps info about related objects (tags, media) in cache field.""" if self._related_info is not None: @@ -403,8 +427,15 @@ class Book(models.Model): 'author', 'kind', 'genre', 'epoch')) tags = split_tags(tags) for category in tags: - rel['tags'][category] = [ - (t.name, t.slug) for t in tags[category]] + cat = [] + for tag in tags[category]: + tag_info = {'slug': tag.slug, 'name': tag.name} + for lc, ln in settings.LANGUAGES: + tag_name = getattr(tag, "name_%s" % lc) + if tag_name: + tag_info["name_%s" % lc] = tag_name + cat.append(tag_info) + rel['tags'][category] = cat for media_format in BookMedia.formats: rel['media'][media_format] = self.has_media(media_format) @@ -488,8 +519,10 @@ class Book(models.Model): def pretty_title(self, html_links=False): book = self rel_info = book.related_info() - names = [(name, Tag.create_url('author', slug)) - for name, slug in rel_info['tags']['author']] + names = [(related_tag_name(tag), Tag.create_url('author', tag['slug'])) + for tag in rel_info['tags'].get('author', ())] + import logging + logging.info("%s, %s" % (book.slug, unicode(rel_info['tags'].get('author', ())))) if 'parents' in rel_info: books = [(name, Book.create_url(slug)) for name, slug in rel_info['parents']] @@ -512,10 +545,11 @@ class Book(models.Model): """ # get relevant books and their tags objects = cls.tagged.with_all(tags) + parents = objects.filter(html_file='').only('slug') # eliminate descendants l_tags = Tag.objects.filter(category='book', - slug__in=[book.book_tag_slug() for book in objects.iterator()]) - descendants_keys = [book.pk for book in cls.tagged.with_any(l_tags).iterator()] + slug__in=[book.book_tag_slug() for book in parents.iterator()]) + descendants_keys = [book.pk for book in cls.tagged.with_any(l_tags).only('pk').iterator()] if descendants_keys: objects = objects.exclude(pk__in=descendants_keys) @@ -561,6 +595,7 @@ class Book(models.Model): return books_by_author, orphans, books_by_parent _audiences_pl = { + "SP": (1, u"szkoła podstawowa"), "SP1": (1, u"szkoła podstawowa"), "SP2": (1, u"szkoła podstawowa"), "P": (1, u"szkoła podstawowa"), @@ -570,7 +605,7 @@ class Book(models.Model): } def audiences_pl(self): audiences = self.extra_info.get('audiences', []) - audiences = sorted(set([self._audiences_pl[a] for a in audiences])) + audiences = sorted(set([self._audiences_pl.get(a, (99, a)) for a in audiences])) return [a[1] for a in audiences] def choose_fragment(self):