predictable urls to cover images
[redakcja.git] / apps / cover / views.py
1 # -*- coding: utf-8 -*-
2 #
3 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 #
6 import os.path
7 from django.conf import settings
8 from django.contrib.auth.decorators import permission_required
9 from django.http import HttpResponse, HttpResponseRedirect, Http404
10 from django.shortcuts import get_object_or_404, render
11 from django.views.decorators.csrf import csrf_exempt
12 from django.views.decorators.http import require_POST
13 from catalogue.helpers import active_tab
14 from catalogue.models import Chunk
15 from cover.models import Image
16 from cover import forms
17
18 PREVIEW_SIZE = (216, 300)
19
20
21 def preview(request, book, chunk=None, rev=None):
22     """Creates a cover image.
23
24     If chunk and rev number are given, use version from given revision.
25     If rev is not given, use publishable version.
26     """
27     from PIL import Image
28     from librarian.cover import make_cover
29     from librarian.dcparser import BookInfo
30
31     chunk = Chunk.get(book, chunk)
32     if rev is not None:
33         try:
34             revision = chunk.at_revision(rev)
35         except Chunk.change_model.DoesNotExist:
36             raise Http404
37     else:
38         revision = chunk.publishable()
39         if revision is None:
40             raise Http404
41     xml = revision.materialize().encode('utf-8')
42
43     try:
44         info = BookInfo.from_string(xml)
45     except:
46         return HttpResponseRedirect(os.path.join(settings.STATIC_URL, "img/sample_cover.png"))
47     cover = make_cover(info)
48     response = HttpResponse(content_type=cover.mime_type())
49     img = cover.image().resize(PREVIEW_SIZE, Image.ANTIALIAS)
50     img.save(response, cover.format)
51     return response
52
53
54 @csrf_exempt
55 @require_POST
56 def preview_from_xml(request):
57     from hashlib import sha1
58     from PIL import Image
59     from os import makedirs
60     from lxml import etree
61     from librarian.cover import make_cover
62     from librarian.dcparser import BookInfo
63
64     xml = request.POST['xml']
65     try:
66         info = BookInfo.from_string(xml.encode('utf-8'))
67     except:
68         return HttpResponse(os.path.join(settings.STATIC_URL, "img/sample_cover.png"))
69     coverid = sha1(etree.tostring(info.to_etree())).hexdigest()
70     cover = make_cover(info)
71
72     cover_dir = 'cover/preview'
73     try:
74         makedirs(os.path.join(settings.MEDIA_ROOT, cover_dir))
75     except OSError:
76         pass
77     fname = os.path.join(cover_dir, "%s.%s" % (coverid, cover.ext()))
78     img = cover.image().resize(PREVIEW_SIZE, Image.ANTIALIAS)
79     img.save(os.path.join(settings.MEDIA_ROOT, fname))
80     return HttpResponse(os.path.join(settings.MEDIA_URL, fname))
81
82
83 @active_tab('cover')
84 def image(request, pk):
85     img = get_object_or_404(Image, pk=pk)
86
87     if request.user.has_perm('cover.change_image'):
88         if request.method == "POST":
89             form = forms.ImageEditForm(request.POST, request.FILES, instance=img)
90             if form.is_valid():
91                 form.save()
92                 return HttpResponseRedirect(img.get_absolute_url())
93         else:
94             form = forms.ImageEditForm(instance=img)
95         editable = True
96     else:
97         form = forms.ReadonlyImageEditForm(instance=img)
98         editable = False
99
100     return render(request, "cover/image_detail.html", {
101         "object": Image.objects.get(id=img.id),
102         "form": form,
103         "editable": editable,
104     })
105
106
107 def image_file(request, pk):
108     img = get_object_or_404(Image, pk=pk)
109     return HttpResponseRedirect(img.file.url)
110
111
112 @active_tab('cover')
113 def image_list(request):
114     return render(request, "cover/image_list.html", {
115         'object_list': Image.objects.all(),
116         'can_add': request.user.has_perm('cover.add_image'),
117     })
118
119
120 @permission_required('cover.add_image')
121 @active_tab('cover')
122 def add_image(request):
123     form = ff = None
124     if request.method == 'POST':
125         if request.POST.get('form_id') == 'flickr':
126             ff = forms.FlickrForm(request.POST)
127             if ff.is_valid():
128                 form = forms.ImageAddForm(ff.cleaned_data)
129         else:
130             form = forms.ImageAddForm(request.POST, request.FILES)
131             if form.is_valid():
132                 obj = form.save()
133                 return HttpResponseRedirect(obj.get_absolute_url())
134     if form is None:
135         form = forms.ImageAddForm()
136     if ff is None:
137         ff = forms.FlickrForm()
138     return render(request, 'cover/add_image.html', {
139             'form': form,
140             'ff': ff,
141         })