# 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 _
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)
def post_publish(sender, **kwargs):
permanent_cache.delete('catalogue.book_list')
+ permanent_cache.delete('catalogue.catalogue')
Book.published.connect(post_publish)
<div id="header">
<a href="/"><img src="{% static "img/logo-220.png" %}" alt="Wolne Lektury" /></a>
</div>
- <div id="themes">
- <ol>
- {% for theme, fragments in book_themes %}
- <li>{{ theme }}:
- {% for fragment in fragments %}
- <a href="#m{{ fragment.anchor }}">{{ forloop.counter }}</a>
- {% endfor %}
- </li>
- {% endfor %}
- </ol>
- </div>
{{ book.html_file.read|safe }}
{{ piwik_tag|safe }}
</body>
</a></p>
<h2 class="white-box">{% trans "Authors" %}<a name="autorzy"></a></h2>
- <div class="white-box">{% tag_list categories.author %}</div>
+ <div class="white-box">{{ output.author }}</div>
<h2 class="white-box">{% trans "Kinds" %}<a name="rodzaje"></a></h2>
- <div class="white-box" lang="pl">{% tag_list categories.kind %}</div>
+ <div class="white-box" lang="pl">{{ output.kind }}</div>
<h2 class="white-box">{% trans "Genres" %}<a name="gatunki"></a></h2>
- <div class="white-box" lang="pl">{% tag_list categories.genre %}</div>
+ <div class="white-box" lang="pl">{{ output.genre }}</div>
<h2 class="white-box">{% trans "Epochs" %}<a name="epoki"></a></h2>
- <div class="white-box" lang="pl">{% tag_list categories.epoch %}</div>
+ <div class="white-box" lang="pl">{{ output.epoch }}</div>
<h2 class="white-box">{% trans "Themes and topics" %}<a name="motywy"></a></h2>
- <div class="white-box" lang="pl">{% tag_list fragment_tags %}</div>
+ <div class="white-box" lang="pl">{{ output.theme }}</div>
<h2 class="white-box">{% trans "Collections" %}<a name="kolekcje"></a></h2>
- <div class="white-box" lang="pl">{% collection_list collections %}</div>
+ <div class="white-box" lang="pl">{{ output.collections }}</div>
</div>
{% endblock %}
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
@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)}
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',
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:
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})
context_instance=RequestContext(request))
-@never_cache
def tagged_object_list(request, tags=''):
try:
tags = models.Tag.get_tag_list(tags)
context_instance=RequestContext(request))
-@never_cache
def book_detail(request, slug):
try:
book = models.Book.objects.get(slug=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))
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:
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
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, [])
# 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
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(),
};
var ajaxable_callbacks = {
- 'social-book-sets': location.reload
+ 'social-book-sets': function() {location.reload();}
};
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))
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()
-Subproject commit 3754989331c91f1d78cd5c1904f768a4cf80f07a
+Subproject commit 181c5739f47d2adb00ba115bb4766584a1bc37e4
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
)
MIDDLEWARE_CLASSES = [
- 'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'piwik.django.middleware.PiwikMiddleware',
'maintenancemode.middleware.MaintenanceModeMiddleware',
'django.middleware.common.CommonMiddleware',
- 'django.middleware.cache.FetchFromCacheMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'fnpdjango.middleware.SetRemoteAddrFromXRealIP',
]
'TIMEOUT': 86400,
},
}
-CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True