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