From: Radek Czajka Date: Fri, 26 Apr 2013 14:29:40 +0000 (+0200) Subject: Merge branch 'master' into funding X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/cda147aa999b09a14dacb097d91638f6b9cca236?hp=676af187437d5baf0543cadc200efb476b062e4b Merge branch 'master' into funding --- diff --git a/apps/catalogue/models/bookmedia.py b/apps/catalogue/models/bookmedia.py index bf05e214e..fb5d58806 100644 --- a/apps/catalogue/models/bookmedia.py +++ b/apps/catalogue/models/bookmedia.py @@ -2,6 +2,7 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +import json from collections import namedtuple from django.db import models from django.utils.translation import ugettext_lazy as _ @@ -60,6 +61,9 @@ class BookMedia(models.Model): remove_zip("%s_%s" % (self.book.slug, self.type)) extra_info = self.extra_info + if isinstance(extra_info, basestring): + # Walkaround for weird jsonfield 'no-decode' optimization. + extra_info = json.loads(extra_info) extra_info.update(self.read_meta()) self.extra_info = extra_info self.source_sha1 = self.read_source_sha1(self.file.path, self.type) diff --git a/apps/catalogue/models/listeners.py b/apps/catalogue/models/listeners.py index 41c974ade..cb106166e 100644 --- a/apps/catalogue/models/listeners.py +++ b/apps/catalogue/models/listeners.py @@ -53,6 +53,7 @@ post_save.connect(_post_save_handler) def post_publish(sender, **kwargs): permanent_cache.delete('catalogue.book_list') + permanent_cache.delete('catalogue.catalogue') Book.published.connect(post_publish) diff --git a/apps/catalogue/templates/catalogue/book_text.html b/apps/catalogue/templates/catalogue/book_text.html index 6addd41f9..aa2b39298 100644 --- a/apps/catalogue/templates/catalogue/book_text.html +++ b/apps/catalogue/templates/catalogue/book_text.html @@ -62,17 +62,6 @@ -
-
    - {% for theme, fragments in book_themes %} -
  1. {{ theme }}: - {% for fragment in fragments %} - {{ forloop.counter }} - {% endfor %} -
  2. - {% endfor %} -
-
{{ book.html_file.read|safe }} {{ piwik_tag|safe }} diff --git a/apps/catalogue/templates/catalogue/catalogue.html b/apps/catalogue/templates/catalogue/catalogue.html index 228a4152f..c7cee4096 100644 --- a/apps/catalogue/templates/catalogue/catalogue.html +++ b/apps/catalogue/templates/catalogue/catalogue.html @@ -17,22 +17,22 @@

{% trans "Authors" %}

-
{% tag_list categories.author %}
+
{{ output.author }}

{% trans "Kinds" %}

-
{% tag_list categories.kind %}
+
{{ output.kind }}

{% trans "Genres" %}

-
{% tag_list categories.genre %}
+
{{ output.genre }}

{% trans "Epochs" %}

-
{% tag_list categories.epoch %}
+
{{ output.epoch }}

{% trans "Themes and topics" %}

-
{% tag_list fragment_tags %}
+
{{ output.theme }}

{% trans "Collections" %}

-
{% collection_list collections %}
+
{{ output.collections }}
{% endblock %} diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index e61feb6c2..92ecebf00 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -18,7 +18,6 @@ from django.utils.datastructures import SortedDict from django.utils.http import urlquote_plus from django.utils import translation from django.utils.translation import ugettext as _, ugettext_lazy -from django.views.decorators.cache import never_cache from django.views.decorators.vary import vary_on_headers from ajaxable.utils import JSONResponse, AjaxableFormView @@ -37,16 +36,17 @@ permanent_cache = get_cache('permanent') @vary_on_headers('X-Requested-With') def catalogue(request): - tags = models.Tag.objects.exclude( - category__in=('set', 'book')).exclude(book_count=0) - tags = list(tags) - for tag in tags: - tag.count = tag.book_count - categories = split_tags(tags) - fragment_tags = categories.get('theme', []) - collections = models.Collection.objects.all() - - if request.is_ajax(): + cache_key='catalogue.catalogue' + output = permanent_cache.get(cache_key) + if output is None: + tags = models.Tag.objects.exclude( + category__in=('set', 'book')).exclude(book_count=0) + tags = list(tags) + for tag in tags: + tag.count = tag.book_count + categories = split_tags(tags) + fragment_tags = categories.get('theme', []) + collections = models.Collection.objects.all() render_tag_list = lambda x: render_to_string( 'catalogue/tag_list.html', tag_list(x)) output = {'theme': render_tag_list(fragment_tags)} @@ -54,13 +54,16 @@ def catalogue(request): output[category] = render_tag_list(tags) output['collections'] = render_to_string( 'catalogue/collection_list.html', collection_list(collections)) + permanent_cache.set(cache_key, output) + if request.is_ajax(): return JSONResponse(output) else: return render_to_response('catalogue/catalogue.html', locals(), context_instance=RequestContext(request)) -def book_list(request, filter=None, template_name='catalogue/book_list.html', +def book_list(request, filter=None, get_filter=None, + template_name='catalogue/book_list.html', nav_template_name='catalogue/snippets/book_list_nav.html', list_template_name='catalogue/snippets/book_list.html', cache_key='catalogue.book_list', @@ -71,6 +74,8 @@ def book_list(request, filter=None, template_name='catalogue/book_list.html', if cached is not None: rendered_nav, rendered_book_list = cached else: + if get_filter: + filter = get_filter() books_by_author, orphans, books_by_parent = models.Book.book_list(filter) books_nav = SortedDict() for tag in books_by_author: @@ -98,11 +103,13 @@ def daisy_list(request): def collection(request, slug): coll = get_object_or_404(models.Collection, slug=slug) - slugs = coll.book_slugs.split() - # allow URIs - slugs = [slug.rstrip('/').rsplit('/', 1)[-1] if '/' in slug else slug - for slug in slugs] - return book_list(request, Q(slug__in=slugs), + def get_filter(): + slugs = coll.book_slugs.split() + # allow URIs + slugs = [slug.rstrip('/').rsplit('/', 1)[-1] if '/' in slug else slug + for slug in slugs] + return Q(slug__in=slugs) + return book_list(request, get_filter=get_filter, template_name='catalogue/collection.html', cache_key='catalogue.collection:%s' % coll.slug, context={'collection': coll}) @@ -122,7 +129,6 @@ def differentiate_tags(request, tags, ambiguous_slugs): context_instance=RequestContext(request)) -@never_cache def tagged_object_list(request, tags=''): try: tags = models.Tag.get_tag_list(tags) @@ -231,7 +237,6 @@ def book_fragments(request, slug, theme_slug): context_instance=RequestContext(request)) -@never_cache def book_detail(request, slug): try: book = models.Book.objects.get(slug=slug) @@ -287,13 +292,6 @@ def book_text(request, slug): if not book.has_html_file(): raise Http404 - book_themes = {} - for fragment in book.fragments.all().iterator(): - for theme in fragment.tags.filter(category='theme').iterator(): - book_themes.setdefault(theme, []).append(fragment) - - book_themes = book_themes.items() - book_themes.sort(key=lambda s: s[0].sort_key) related = book.related_info() return render_to_response('catalogue/book_text.html', locals(), context_instance=RequestContext(request)) diff --git a/apps/dictionary/views.py b/apps/dictionary/views.py index 4208d9b4c..76c89cd85 100755 --- a/apps/dictionary/views.py +++ b/apps/dictionary/views.py @@ -11,7 +11,7 @@ class NotesView(ListView): self.letters = ["0-9"] + [chr(a) for a in range(ord('a'), ord('z')+1)] self.letter = self.kwargs.get('letter') - objects = Note.objects.all() + objects = Note.objects.select_related('book').all() if self.letter == "0-9": objects = objects.filter(sort_key__regex=r"^[0-9]") elif self.letter: diff --git a/apps/oai/views.py b/apps/oai/views.py index af4bd1c2c..5ef5bd43b 100644 --- a/apps/oai/views.py +++ b/apps/oai/views.py @@ -44,7 +44,6 @@ def qdc_writer(element, metadata): for name in ['hasPart', 'isPartOf']: for value in map.get(name, []): - print "%s %s" % (name, value) e = SubElement(element, nsdcterms(name), nsmap=nsmap) e.text = value diff --git a/apps/social/views.py b/apps/social/views.py index 27769d740..8af17da4f 100644 --- a/apps/social/views.py +++ b/apps/social/views.py @@ -61,7 +61,10 @@ class ObjectSetsFormView(AjaxableFormView): return (obj, request.user), {} +@require_POST def unlike_book(request, slug): + if not request.user.is_authenticated(): + return HttpResponseForbidden('Login required.') book = get_object_or_404(Book, slug=slug) if likes(request.user, book): set_sets(request.user, book, []) diff --git a/apps/sponsors/models.py b/apps/sponsors/models.py index 24d302208..cbc8d9ba4 100644 --- a/apps/sponsors/models.py +++ b/apps/sponsors/models.py @@ -2,6 +2,7 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +import json import time from StringIO import StringIO from django.db import models @@ -85,6 +86,9 @@ class SponsorPage(models.Model): html = property(fget=html) def save(self, *args, **kwargs): + if isinstance(self.sponsors, basestring): + # Walkaround for weird jsonfield 'no-decode' optimization. + self.sponsors = json.loads(self.sponsors) self.render_sprite() self._html = render_to_string('sponsors/page.html', { 'sponsors': self.populated_sponsors(), diff --git a/apps/wolnelektury_core/static/js/dialogs.js b/apps/wolnelektury_core/static/js/dialogs.js index bd412bc74..3b7553b30 100755 --- a/apps/wolnelektury_core/static/js/dialogs.js +++ b/apps/wolnelektury_core/static/js/dialogs.js @@ -148,7 +148,7 @@ }; var ajaxable_callbacks = { - 'social-book-sets': location.reload + 'social-book-sets': function() {location.reload();} }; diff --git a/apps/wolnelektury_core/views.py b/apps/wolnelektury_core/views.py index 7f2940115..77cd01681 100644 --- a/apps/wolnelektury_core/views.py +++ b/apps/wolnelektury_core/views.py @@ -19,7 +19,6 @@ from ajaxable.utils import placeholdized from social.templatetags.social_tags import choose_cite -@never_cache def main_page(request): last_published = Book.objects.filter(parent=None).order_by('-created_at')[:4] cite = choose_cite(RequestContext(request)) @@ -90,6 +89,7 @@ def logout_then_redirect(request): return HttpResponseRedirect(urlquote_plus(request.GET.get('next', '/'), safe='/?=')) +@never_cache def clock(request): """ Provides server UTC time for jquery.countdown, in a format suitable for Date.parse() diff --git a/lib/librarian b/lib/librarian index 375498933..181c5739f 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 3754989331c91f1d78cd5c1904f768a4cf80f07a +Subproject commit 181c5739f47d2adb00ba115bb4766584a1bc37e4 diff --git a/lib/sortify.py b/lib/sortify.py old mode 100755 new mode 100644 diff --git a/requirements.txt b/requirements.txt index 836f6d309..572251ae4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ django-pipeline>=1.2.24,<1.3 django-pagination>=1.0 django-maintenancemode>=0.10 django-piston>=0.2.2.1,<0.2.3 -django-jsonfield>=0.9,<0.10 +-e git+git://github.com/bradjasper/django-jsonfield.git@e67ec8c3652e61d8b47cc8db012a63f5ad39323d#egg=django-jsonfield django-picklefield #django-allauth<0.10 with migration fix diff --git a/wolnelektury/settings/__init__.py b/wolnelektury/settings/__init__.py index 1ff9e0ef1..b3950fccb 100644 --- a/wolnelektury/settings/__init__.py +++ b/wolnelektury/settings/__init__.py @@ -26,7 +26,6 @@ TEMPLATE_CONTEXT_PROCESSORS = ( ) MIDDLEWARE_CLASSES = [ - 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -37,7 +36,6 @@ MIDDLEWARE_CLASSES = [ 'piwik.django.middleware.PiwikMiddleware', 'maintenancemode.middleware.MaintenanceModeMiddleware', 'django.middleware.common.CommonMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'fnpdjango.middleware.SetRemoteAddrFromXRealIP', ] diff --git a/wolnelektury/settings/cache.py b/wolnelektury/settings/cache.py index 14edd53df..3e27b5fcb 100644 --- a/wolnelektury/settings/cache.py +++ b/wolnelektury/settings/cache.py @@ -22,4 +22,3 @@ CACHES = { 'TIMEOUT': 86400, }, } -CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True