Cover quick import.
[redakcja.git] / src / cover / forms.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 from io import BytesIO
5
6 from django import forms
7 from django.conf import settings
8 from django.utils.translation import ugettext_lazy as _, ugettext
9 from cover.models import Image
10 from django.utils.safestring import mark_safe
11 from PIL import Image as PILImage
12
13 from cover.utils import get_import_data, FlickrError, URLOpener
14
15
16 class ImageAddForm(forms.ModelForm):
17     class Meta:
18         model = Image
19         exclude = [] 
20
21     def __init__(self, *args, **kwargs):
22         super(ImageAddForm, self).__init__(*args, **kwargs)
23         self.fields['file'].required = False
24         self.fields['use_file'].required = False
25         self.fields['cut_top'].required = False
26         self.fields['cut_left'].required = False
27         self.fields['cut_bottom'].required = False
28         self.fields['cut_right'].required = False
29
30     def clean_download_url(self):
31         cl = self.cleaned_data['download_url'] or None
32         if cl is not None:
33             try:
34                 img = Image.objects.get(download_url=cl)
35             except Image.DoesNotExist:
36                 pass
37             else:
38                 raise forms.ValidationError(mark_safe(
39                     ugettext('Image <a href="%(url)s">already in repository</a>.')
40                     % {'url': img.get_absolute_url()}))
41         return cl
42
43     def clean_source_url(self):
44         source_url = self.cleaned_data['source_url'] or None
45         if source_url is not None:
46             same_source = Image.objects.filter(source_url=source_url)
47             if same_source:
48                 raise forms.ValidationError(mark_safe(
49                     ugettext('Image <a href="%(url)s">already in repository</a>.')
50                     % {'url': same_source.first().get_absolute_url()}))
51         return source_url
52
53     def clean(self):
54         cleaned_data = super(ImageAddForm, self).clean()
55         download_url = cleaned_data.get('download_url', None)
56         uploaded_file = cleaned_data.get('file', None)
57         if not download_url and not uploaded_file:
58             raise forms.ValidationError(ugettext('No image specified'))
59         if download_url:
60             image_data = URLOpener().open(download_url).read()
61             width, height = PILImage.open(BytesIO(image_data)).size
62         else:
63             width, height = PILImage.open(uploaded_file.file).size
64         min_width, min_height = settings.MIN_COVER_SIZE
65         if width < min_width or height < min_height:
66             raise forms.ValidationError(ugettext('Image too small: %sx%s, minimal dimensions %sx%s') %
67                                         (width, height, min_width, min_height))
68         return cleaned_data
69
70
71 class ImageEditForm(forms.ModelForm):
72     """Form used for editing a Book."""
73     class Meta:
74         model = Image
75         exclude = ['download_url']
76
77     def clean(self):
78         cleaned_data = super(ImageEditForm, self).clean()
79         uploaded_file = cleaned_data.get('file', None)
80         width, height = PILImage.open(uploaded_file.file).size
81         min_width, min_height = settings.MIN_COVER_SIZE
82         if width < min_width or height < min_height:
83             raise forms.ValidationError(ugettext('Image too small: %sx%s, minimal dimensions %sx%s') %
84                                         (width, height, min_width, min_height))
85
86
87 class ReadonlyImageEditForm(ImageEditForm):
88     """Form used for not editing an Image."""
89
90     def __init__(self, *args, **kwargs):
91         super(ReadonlyImageEditForm, self).__init__(*args, **kwargs)
92         for field in self.fields.values():
93             field.widget.attrs.update({"readonly": True})
94
95     def save(self, *args, **kwargs):
96         raise AssertionError("ReadonlyImageEditForm should not be saved.")
97
98
99 class ImportForm(forms.Form):
100     source_url = forms.URLField(label=_('WikiCommons, MNW or Flickr URL'))
101
102     def clean_source_url(self):
103         url = self.cleaned_data['source_url']
104         try:
105             import_data = get_import_data(url)
106         except FlickrError as e:
107             raise forms.ValidationError(e)
108         for field_name in ('license_url', 'license_name', 'author', 'title', 'download_url'):
109             self.cleaned_data[field_name] = import_data[field_name]
110         return import_data['source_url']
111