0001-misc-allow-page-picture-to-be-svg-34334.patch
combo/data/models.py | ||
---|---|---|
162 | 162 |
def natural_key(self): |
163 | 163 |
return (self.get_online_url().strip('/'), ) |
164 | 164 | |
165 |
def picture_extension(self): |
|
166 |
if not self.picture: |
|
167 |
return None |
|
168 |
return os.path.splitext(self.picture.name)[-1] |
|
169 | ||
165 | 170 |
def save(self, *args, **kwargs): |
166 | 171 |
if not self.id: |
167 | 172 |
self.related_cells = {'cell_types': []} |
combo/manager/fields.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# |
|
3 |
# combo - content management system |
|
4 |
# Copyright (C) 2015-2019 Entr'ouvert |
|
5 |
# |
|
6 |
# This program is free software: you can redistribute it and/or modify it |
|
7 |
# under the terms of the GNU Affero General Public License as published |
|
8 |
# by the Free Software Foundation, either version 3 of the License, or |
|
9 |
# (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU Affero General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU Affero General Public License |
|
17 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
18 | ||
19 | ||
20 |
from django.core import validators |
|
21 |
from django import forms |
|
22 | ||
23 | ||
24 |
def get_available_image_extensions(): |
|
25 |
return validators.get_available_image_extensions() + ['svg'] |
|
26 | ||
27 |
validate_image_file_extension = validators.FileExtensionValidator( |
|
28 |
allowed_extensions=get_available_image_extensions(), |
|
29 |
) |
|
30 | ||
31 |
class ImageIncludingSvgField(forms.ImageField): |
|
32 |
default_validators = [validate_image_file_extension] |
|
33 | ||
34 |
def to_python(self, data): |
|
35 |
if data.name and data.name.endswith('.svg'): |
|
36 |
# bypass image field Pillow check |
|
37 |
return super(forms.ImageField, self).to_python(data) |
|
38 |
return super(ImageIncludingSvgField, self).to_python(data) |
combo/manager/forms.py | ||
---|---|---|
23 | 23 | |
24 | 24 |
from combo.data.models import Page |
25 | 25 | |
26 |
from .fields import ImageIncludingSvgField |
|
27 | ||
26 | 28 | |
27 | 29 |
class PageEditTitleForm(forms.ModelForm): |
28 | 30 |
class Meta: |
... | ... | |
53 | 55 |
class Meta: |
54 | 56 |
model = Page |
55 | 57 |
fields = ('picture',) |
58 |
field_classes = { |
|
59 |
'picture': ImageIncludingSvgField |
|
60 |
} |
|
56 | 61 | |
57 | 62 | |
58 | 63 |
class PageVisibilityForm(forms.ModelForm): |
combo/manager/static/css/combo.manager.css | ||
---|---|---|
374 | 374 | |
375 | 375 |
img.page-picture { |
376 | 376 |
max-width: 100%; |
377 |
max-height: 250px; |
|
377 | 378 |
} |
378 | 379 | |
379 | 380 |
span.error { |
combo/manager/templates/combo/page_view.html | ||
---|---|---|
70 | 70 |
<p> |
71 | 71 |
<label>{% trans 'Picture:' %}</label> |
72 | 72 |
{% if object.picture %} |
73 |
{% thumbnail object.picture "320x240" crop="50% 25%" as im %} |
|
74 |
<img class="page-picture" src="{{im.url}}"/> |
|
73 |
{% if object.picture_extension != '.svg' %} |
|
74 |
{% thumbnail object.picture "320x240" crop="50% 25%" as im %} |
|
75 |
<img class="page-picture" src="{{im.url}}"/> |
|
76 |
{% endthumbnail %} |
|
77 |
{% else %} |
|
78 |
<img class="page-picture" src="{{page.picture.url}}"/> |
|
79 |
{% endif %} |
|
75 | 80 |
(<a href="{% url 'combo-manager-page-remove-picture' pk=object.id %}">{% trans 'remove' %}</a>) |
76 |
{% endthumbnail %} |
|
77 | 81 |
{% else %}<i>{% trans 'none' %}</i>{% endif %} |
78 | 82 |
(<a rel="popup" href="{% url 'combo-manager-page-edit-picture' pk=object.id %}">{% trans 'change' %}</a>) |
79 | 83 |
</p> |
tests/test_manager.py | ||
---|---|---|
170 | 170 |
resp = resp.follow() |
171 | 171 |
assert '<h2>Page - One</h2>' in resp.text |
172 | 172 |
assert '<img' in resp.text |
173 |
assert 'src="/media/cache/' in resp.text |
|
173 | 174 |
resp = resp.click(href='.*/remove-picture/') |
174 | 175 |
resp = resp.follow() |
175 | 176 |
assert '<h2>Page - One</h2>' in resp.text |
176 | 177 |
assert not '<img' in resp.text |
177 | 178 | |
179 |
resp = resp.click(href='.*/picture/') |
|
180 |
resp.form['picture'] = Upload('black.svg', |
|
181 |
'<svg xmlns="http://www.w3.org/2000/svg"/>', 'image/svg+xml') |
|
182 |
resp = resp.form.submit() |
|
183 |
assert resp.location.endswith('/manage/pages/%s/' % page.id) |
|
184 |
resp = resp.follow() |
|
185 |
assert '<h2>Page - One</h2>' in resp.text |
|
186 |
assert '<img' in resp.text |
|
187 |
assert Page.objects.get(id=page.id).picture.url in resp.text |
|
188 | ||
178 | 189 |
def test_delete_page(app, admin_user): |
179 | 190 |
Page.objects.all().delete() |
180 | 191 |
page = Page(title='One', slug='one', template_name='standard') |
181 |
- |