From: Jan Szejko Date: Wed, 13 Apr 2016 08:17:15 +0000 (+0200) Subject: Merge branch 'dev' X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/9a938c8b406ce05e3bca4a5a483d473ece9e17b0?ds=sidebyside;hp=-c Merge branch 'dev' Conflicts: src/api/management/commands/mobileinit.py src/catalogue/templates/catalogue/inline_tag_list.html src/catalogue/templates/catalogue/plain_list.html src/catalogue/views.py src/wolnelektury/static/scss/main/book_box.scss src/wolnelektury/static/scss/main/header.scss src/wolnelektury/templates/main_page.html src/wolnelektury/templates/superbase.html --- 9a938c8b406ce05e3bca4a5a483d473ece9e17b0 diff --combined src/api/management/commands/mobileinit.py index ccbff3e21,ed4d624f9..ccf27bc76 --- a/src/api/management/commands/mobileinit.py +++ b/src/api/management/commands/mobileinit.py @@@ -97,7 -97,7 +97,7 @@@ CREATE TABLE state (last_checked INTEGE """ db.executescript(schema) - db.execute("INSERT INTO state VALUES (:last_checked)", locals()) + db.execute("INSERT INTO state VALUES (:last_checked)", {'last_checked': last_checked}) return db @@@ -133,29 -133,30 +133,30 @@@ categories = {'author': 'autor' def add_book(db, book): - title = book.title if book.html_file: html_file = book.html_file.url html_file_size = book.html_file.size else: html_file = html_file_size = None - if book.cover: - cover = book.cover.url - else: - cover = None - parent = book.parent_id - parent_number = book.parent_number - sort_key = book.sort_key - size_str = pretty_size(html_file_size) - authors = book.author_unicode() - db.execute(book_sql, locals()) + db.execute(book_sql, { + 'title': book.title, + 'cover': book.cover.url if book.cover else None, + 'html_file': html_file, + 'html_file_size': html_file_size, + 'parent': book.parent_id, + 'parent_number': book.parent_number, + 'sort_key': book.sort_key, + 'size_str': pretty_size(html_file_size), - 'authors': ", ".join(t.name for t in book.tags.filter(category='author')), ++ 'authors': book.author_unicode(), + }) def add_tag(db, tag): - category = categories[tag.category] - name = tag.name - sort_key = tag.sort_key - books = Book.tagged_top_level([tag]) - book_ids = ','.join(str(b.id) for b in books) - db.execute(tag_sql, locals()) + book_ids = ','.join(str(book_id) for book_id in books.values_list('id', flat=True)) + db.execute(tag_sql, { + 'category': categories[tag.category], + 'name': tag.name, + 'sort_key': tag.sort_key, + 'book_ids': book_ids, + }) diff --combined src/catalogue/helpers.py index e47607928,f74fad3e3..97c63d08c --- a/src/catalogue/helpers.py +++ b/src/catalogue/helpers.py @@@ -3,6 -3,9 +3,9 @@@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from django.conf import settings + from django.contrib.contenttypes.models import ContentType + from django.core.cache import cache + from .models import Tag, Book from os.path import getmtime import cPickle @@@ -36,7 -39,6 +39,6 @@@ def get_top_level_related_tags(tags, ca 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) @@@ -57,7 -59,7 +59,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: @@@ -86,3 -88,16 +88,16 @@@ with open(settings.CATALOGUE_COUNTERS_FILE, 'w') as f: cPickle.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(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 diff --combined src/catalogue/models/book.py index d3e2a7756,676f9c028..0ed97161b --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@@ -4,9 -4,7 +4,9 @@@ # from collections import OrderedDict from random import randint +import os.path import re +import urllib from django.conf import settings from django.db import connection, models, transaction from django.db.models import permalink @@@ -21,10 -19,9 +21,10 @@@ from newtagging import manager from catalogue import constants from catalogue.fields import EbookField from catalogue.models import Tag, Fragment, BookMedia -from catalogue.utils import create_zip +from catalogue.utils import create_zip, gallery_url, gallery_path from catalogue import app_settings from catalogue import tasks +from wolnelektury.utils import makedirs bofh_storage = BofhFileSystemStorage() @@@ -92,7 -89,7 +92,7 @@@ class Book(models.Model) pass class Meta: - ordering = ('sort_key',) + ordering = ('sort_key_author', 'sort_key') verbose_name = _('book') verbose_name_plural = _('books') app_label = 'catalogue' @@@ -106,11 -103,8 +106,11 @@@ except AttributeError: return '' - def author_str(self): - return ", ".join(str(t) for t in self.tags.filter(category='author')) + def authors(self): + return self.tags.filter(category='author') + + def author_unicode(self): + return ", ".join(self.authors().values_list('name', flat=True)) def save(self, force_insert=False, force_update=False, **kwargs): from sortify import sortify @@@ -119,8 -113,8 +119,8 @@@ self.title = unicode(self.title) # ??? try: - author = self.tags.filter(category='author')[0].sort_key - except IndexError: + author = self.authors().first().sort_key + except AttributeError: author = u'' self.sort_key_author = author @@@ -137,12 -131,6 +137,12 @@@ def create_url(slug): return 'catalogue.views.book_detail', [slug] + def gallery_path(self): + return gallery_path(self.slug) + + def gallery_url(self): + return gallery_url(self.slug) + @property def name(self): return self.title @@@ -153,9 -141,6 +153,9 @@@ def language_name(self): return dict(settings.LANGUAGES).get(self.language_code(), "") + def is_foreign(self): + return self.language_code() != settings.LANGUAGE_CODE + def has_media(self, type_): if type_ in Book.formats: return bool(getattr(self, "%s_file" % type_)) @@@ -251,21 -236,6 +251,21 @@@ index.index.rollback() raise e + def download_pictures(self, remote_gallery_url): + gallery_path = self.gallery_path() + # delete previous files, so we don't include old files in ebooks + if os.path.isdir(gallery_path): + for filename in os.listdir(gallery_path): + file_path = os.path.join(gallery_path, filename) + os.unlink(file_path) + ilustr_elements = list(self.wldocument().edoc.findall('//ilustr')) + if ilustr_elements: + makedirs(gallery_path) + for ilustr in ilustr_elements: + ilustr_src = ilustr.get('src') + ilustr_path = os.path.join(gallery_path, ilustr_src) + urllib.urlretrieve('%s/%s' % (remote_gallery_url, ilustr_src), ilustr_path) + @classmethod def from_xml_file(cls, xml_file, **kwargs): from django.core.files import File @@@ -284,7 -254,7 +284,7 @@@ @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_tags=True, remote_gallery_url=None): if dont_build is None: dont_build = set() dont_build = set.union(set(dont_build), set(app_settings.DONT_BUILD)) @@@ -352,9 -322,6 +352,9 @@@ cls.repopulate_ancestors() tasks.update_counters.delay() + if remote_gallery_url: + book.download_pictures(remote_gallery_url) + # No saves beyond this point. # Build cover. @@@ -481,7 -448,7 +481,7 @@@ return books def pretty_title(self, html_links=False): - names = [(tag.name, tag.get_absolute_url()) for tag in self.tags.filter(category='author')] + names = [(tag.name, tag.get_absolute_url()) for tag in self.authors().only('name', 'category', 'slug')] books = self.parents() + [self] names.extend([(b.title, b.get_absolute_url()) for b in books]) @@@ -511,7 -478,8 +511,7 @@@ """ books_by_parent = {} - books = cls.objects.all().order_by('parent_number', 'sort_key').only( - 'title', 'parent', 'slug') + books = cls.objects.order_by('parent_number', 'sort_key').only('title', 'parent', 'slug') if book_filter: books = books.filter(book_filter).distinct() @@@ -531,7 -499,7 +531,7 @@@ books_by_author[tag] = [] for book in books_by_parent.get(None, ()): - authors = list(book.tags.filter(category='author')) + authors = list(book.authors().only('pk')) if authors: for author in authors: books_by_author[author].append(book) @@@ -576,6 -544,15 +576,15 @@@ else: return None + def update_popularity(self): + count = self.tags.filter(category='set').values('user').order_by('user').distinct().count() + try: + pop = self.popularity + pop.count = count + pop.save() + except BookPopularity.DoesNotExist: + BookPopularity.objects.create(book=self, count=count) + def add_file_fields(): for format_ in Book.formats: @@@ -595,3 -572,8 +604,8 @@@ ).contribute_to_class(Book, field_name) add_file_fields() + + + class BookPopularity(models.Model): + book = models.OneToOneField(Book, related_name='popularity') + count = models.IntegerField(default=0) diff --combined src/catalogue/templates/catalogue/inline_tag_list.html index f6d59a788,cf53e2d73..802fcb19e --- a/src/catalogue/templates/catalogue/inline_tag_list.html +++ b/src/catalogue/templates/catalogue/inline_tag_list.html @@@ -1,34 -1,29 +1,27 @@@ {% load i18n %} {% load catalogue_tags %} - {% if choices %} - {% if category_choices %} - - {% endif %} - {% if tags %} + + {% if choices %} + {% if category_choices %} - {% endif %} - {% else %} - {% if tags %} -