X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/f3acfae26c01f08232af6f4b48e9a2ea54a0c2da..a6145bb10676f304d4a3de6789c383f1f9326055:/apps/catalogue/models/book.py?ds=inline
diff --git a/apps/catalogue/models/book.py b/apps/catalogue/models/book.py
index 980ad5269..414d1effb 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
@@ -11,14 +11,16 @@ import django.dispatch
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _
import jsonfield
+from fnpdjango.storage import BofhFileSystemStorage
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, related_tag_name
from catalogue import app_settings
from catalogue import tasks
from newtagging import managers
+bofh_storage = BofhFileSystemStorage()
permanent_cache = get_cache('permanent')
@@ -27,6 +29,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 +39,20 @@ 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)
+ null=True, blank=True,
+ upload_to=lambda i, n: 'book/cover/%s.jpg' % i.slug,
+ storage=bofh_storage, max_length=255)
+ # Cleaner version of cover for thumbs
+ cover_thumb = EbookField('cover_thumb', _('cover thumbnail'),
+ null=True, blank=True,
+ upload_to=lambda i, n: 'book/cover_thumb/%s.jpg' % i.slug,
+ max_length=255)
ebook_formats = constants.EBOOK_FORMATS
formats = ebook_formats + ['html', 'xml']
@@ -74,8 +84,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()
@@ -86,10 +97,21 @@ class Book(models.Model):
def get_absolute_url(self):
return ('catalogue.views.book_detail', [self.slug])
+ @staticmethod
+ @permalink
+ def create_url(slug):
+ return ('catalogue.views.book_detail', [slug])
+
@property
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]
@@ -112,7 +134,7 @@ class Book(models.Model):
if self.has_media(type_):
if type_ in Book.formats:
return getattr(self, "%s_file" % type_)
- else:
+ else:
return self.media.filter(type=type_)
else:
return None
@@ -124,7 +146,7 @@ class Book(models.Model):
def get_ogg(self):
return self.get_media("ogg")
def get_daisy(self):
- return self.get_media("daisy")
+ return self.get_media("daisy")
def reset_short_html(self):
if self.id is None:
@@ -135,6 +157,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')
@@ -298,7 +328,8 @@ 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.
if has_own_text:
@@ -380,12 +411,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:
@@ -397,8 +433,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)
@@ -481,19 +524,19 @@ class Book(models.Model):
def pretty_title(self, html_links=False):
book = self
- names = list(book.tags.filter(category='author'))
-
- books = []
- while book:
- books.append(book)
- book = book.parent
- names.extend(reversed(books))
+ rel_info = book.related_info()
+ names = [(related_tag_name(tag), Tag.create_url('author', tag['slug']))
+ for tag in rel_info['tags'].get('author', ())]
+ if 'parents' in rel_info:
+ books = [(name, Book.create_url(slug))
+ for name, slug in rel_info['parents']]
+ names.extend(reversed(books))
+ names.append((self.title, self.get_absolute_url()))
if html_links:
- names = ['%s' % (tag.get_absolute_url(), tag.name) for tag in names]
+ names = ['%s' % (tag[1], tag[0]) for tag in names]
else:
- names = [tag.name for tag in names]
-
+ names = [tag[0] for tag in names]
return ', '.join(names)
@classmethod
@@ -506,10 +549,11 @@ class Book(models.Model):
"""
# get relevant books and their tags
objects = cls.tagged.with_all(tags)
+ parents = objects.exclude(children=None).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)
@@ -528,7 +572,7 @@ class Book(models.Model):
'title', 'parent', 'slug')
if filter:
books = books.filter(filter).distinct()
-
+
book_ids = set(b['pk'] for b in books.values("pk").iterator())
for book in books.iterator():
parent = book.parent_id
@@ -544,7 +588,7 @@ class Book(models.Model):
for tag in Tag.objects.filter(category='author').iterator():
books_by_author[tag] = []
- for book in books_by_parent.get(None,()):
+ for book in books_by_parent.get(None, ()):
authors = list(book.tags.filter(category='author'))
if authors:
for author in authors:
@@ -555,6 +599,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"),
@@ -564,7 +609,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):
@@ -581,6 +626,13 @@ class Book(models.Model):
# add the file fields
for format_ in Book.formats:
field_name = "%s_file" % format_
+ upload_to = (lambda upload_path:
+ lambda i, n: upload_path % i.slug
+ )('book/%s/%%s.%s' % (format_, format_))
EbookField(format_, _("%s file" % format_.upper()),
- upload_to=book_upload_path(format_),
- blank=True, default='').contribute_to_class(Book, field_name)
+ upload_to=upload_to,
+ storage=bofh_storage,
+ max_length=255,
+ blank=True,
+ default=''
+ ).contribute_to_class(Book, field_name)