# -*- coding: utf-8 -*-
+import tempfile
+import zipfile
+
from django.template import RequestContext
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
# ==========
# = Search =
# ==========
-def search(request):
- query = request.GET.get('q', '')
- tags = request.GET.get('tags', '')
- if tags == '':
- tags = []
-
- try:
- tag_list = models.Tag.get_tag_list(tags)
- tag = models.Tag.objects.get(name=query)
- except models.Tag.DoesNotExist:
- try:
- book = models.Book.objects.get(title=query)
- return HttpResponseRedirect(book.get_absolute_url())
- except models.Book.DoesNotExist:
- return HttpResponseRedirect(reverse('catalogue.views.main_page'))
+def _tags_starting_with(prefix, user):
+ books = models.Book.objects.filter(title__icontains=prefix)
+ tags = models.Tag.objects.filter(name__icontains=prefix)
+ if user.is_authenticated():
+ tags = tags.filter(~Q(category='set') | Q(user=user))
else:
- tag_list.append(tag)
- return HttpResponseRedirect(reverse('catalogue.views.tagged_object_list',
- kwargs={'tags': '/'.join(tag.slug for tag in tag_list)}
- ))
+ tags = tags.filter(~Q(category='set'))
+ return list(books) + list(tags)
+
-def tags_starting_with(request):
+def search(request):
+ tags = request.GET.get('tags', '')
+ prefix = request.GET.get('q', '')
+ # Prefix must have at least 2 characters
+ if len(prefix) < 2:
+ return HttpResponse('')
+
try:
- prefix = request.GET['q']
- if len(prefix) < 2:
- raise KeyError
-
- books = models.Book.objects.filter(title__icontains=prefix)
- tags = models.Tag.objects.filter(name__icontains=prefix)
- if request.user.is_authenticated():
- tags = tags.filter(~Q(category='set') | Q(user=request.user))
+ tag_list = models.Tag.get_tag_list(tags)
+ except:
+ tag_list = []
+
+ result = _tags_starting_with(prefix, request.user)
+ if len(result) > 0:
+ tag = result[0]
+ if isinstance(tag, models.Book):
+ return HttpResponseRedirect(tag.get_absolute_url())
else:
- tags = tags.filter(~Q(category='set'))
-
- completions = [book.title for book in books] + [tag.name for tag in tags]
+ tag_list.append(tag)
+
+ return HttpResponseRedirect(reverse('catalogue.views.tagged_object_list',
+ kwargs={'tags': '/'.join(tag.slug for tag in tag_list)}
+ ))
- return HttpResponse('\n'.join(completions))
- except KeyError:
+def tags_starting_with(request):
+ prefix = request.GET['q']
+ # Prefix must have at least 2 characters
+ if len(prefix) < 2:
return HttpResponse('')
+
+ return HttpResponse('\n'.join(tag.name for tag in _tags_starting_with(prefix, request.user)))
# ====================
# = Shelf management =
# ====================
@login_required
-@cache.cache_control(must_revalidate=True, max_age=3600, private=True)
+@cache.never_cache
def user_shelves(request):
shelves = models.Tag.objects.filter(category='set', user=request.user)
new_set_form = forms.NewSetForm()
context_instance=RequestContext(request))
-@cache.cache_control(must_revalidate=True, max_age=3600, private=True)
+@cache.never_cache
def book_sets(request, slug):
book = get_object_or_404(models.Book, slug=slug)
user_sets = models.Tag.objects.filter(category='set', user=request.user)
context_instance=RequestContext(request))
+@cache.never_cache
+def download_shelf(request, slug):
+ """"
+ Create a ZIP archive on disk and transmit it in chunks of 8KB,
+ without loading the whole file into memory. A similar approach can
+ be used for large dynamic PDF files.
+ """
+ shelf = get_object_or_404(models.Tag, slug=slug, category='set')
+
+ # Create a ZIP archive
+ temp = temp = tempfile.TemporaryFile()
+ archive = zipfile.ZipFile(temp, 'w')
+ for book in models.Book.tagged.with_all(shelf):
+ if book.pdf_file:
+ filename = book.pdf_file.path
+ archive.write(filename, str('%s.pdf' % book.slug))
+ if book.odt_file:
+ filename = book.odt_file.path
+ archive.write(filename, str('%s.odt' % book.slug))
+ if book.txt_file:
+ filename = book.txt_file.path
+ archive.write(filename, str('%s.txt' % book.slug))
+ archive.close()
+
+ response = HttpResponse(content_type='application/zip', mimetype='application/x-zip-compressed')
+ response['Content-Disposition'] = 'attachment; filename=%s.zip' % shelf.sort_key
+ response['Content-Length'] = temp.tell()
+
+ temp.seek(0)
+ response.write(temp.read())
+ return response
+
+
@login_required
@require_POST
@cache.never_cache