1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2024-11-26 18:37:12 +00:00

Merge branch 'image_upload' into 'beta'

Move image upload code to form clean

See merge request bde/nk20!112
This commit is contained in:
erdnaxe 2020-09-06 12:30:45 +02:00
commit fcd1bb98a8
3 changed files with 51 additions and 27 deletions

View File

@ -1,7 +1,11 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import io
from PIL import Image
from django import forms from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple
@ -77,6 +81,38 @@ class ImageForm(forms.Form):
width = forms.FloatField(widget=forms.HiddenInput()) width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput()) height = forms.FloatField(widget=forms.HiddenInput())
def clean(self):
"""Load image and crop"""
cleaned_data = super().clean()
# Image size is limited by Django DATA_UPLOAD_MAX_MEMORY_SIZE
image = cleaned_data.get('image')
if image:
# Let Pillow detect and load image
try:
im = Image.open(image)
except OSError:
# Rare case in which Django consider the upload file as an image
# but Pil is unable to load it
raise forms.ValidationError(_('This image cannot be loaded.'))
# Crop image
x = cleaned_data.get('x', 0)
y = cleaned_data.get('y', 0)
w = cleaned_data.get('width', 200)
h = cleaned_data.get('height', 200)
im = im.crop((x, y, x + w, y + h))
im = im.resize(
(settings.PIC_WIDTH, settings.PIC_RATIO * settings.PIC_WIDTH),
Image.ANTIALIAS,
)
# Save
image.file = io.BytesIO()
im.save(image.file, "PNG")
return cleaned_data
class ClubForm(forms.ModelForm): class ClubForm(forms.ModelForm):
def clean(self): def clean(self):

View File

@ -55,12 +55,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
/* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */ /* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */
$("#id_image").change(function (e) { $("#id_image").change(function (e) {
if (this.files && this.files[0]) { if (this.files && this.files[0]) {
var reader = new FileReader(); // Check the image size
reader.onload = function (e) { if (this.files[0].size > 2*1024*1024) {
$("#modal-image").attr("src", e.target.result); alert("Ce fichier est trop volumineux.")
$("#modalCrop").modal("show"); } else {
// Read the selected image file
var reader = new FileReader();
reader.onload = function (e) {
$("#modal-image").attr("src", e.target.result);
$("#modalCrop").modal("show");
}
reader.readAsDataURL(this.files[0]);
} }
reader.readAsDataURL(this.files[0]);
} }
}); });
@ -104,4 +110,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
}); });
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,10 +1,8 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
import io
from datetime import timedelta, date from datetime import timedelta, date
from PIL import Image
from django.conf import settings from django.conf import settings
from django.contrib.auth import logout from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
@ -263,6 +261,7 @@ class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, Det
return context return context
def get_success_url(self): def get_success_url(self):
"""Redirect to profile page after upload"""
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.id}) return reverse_lazy('member:user_detail', kwargs={'pk': self.object.id})
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -271,26 +270,9 @@ class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, Det
return self.form_valid(form) if form.is_valid() else self.form_invalid(form) return self.form_valid(form) if form.is_valid() else self.form_invalid(form)
def form_valid(self, form): def form_valid(self, form):
"""Save image to note"""
image_field = form.cleaned_data['image'] image_field = form.cleaned_data['image']
x = form.cleaned_data['x'] image_field.name = "{}_pic.png".format(self.object.note.pk)
y = form.cleaned_data['y']
w = form.cleaned_data['width']
h = form.cleaned_data['height']
# image crop and resize
image_file = io.BytesIO(image_field.read())
# ext = image_field.name.split('.')[-1].lower()
# TODO: support GIF format
image = Image.open(image_file)
image = image.crop((x, y, x + w, y + h))
image_clean = image.resize((settings.PIC_WIDTH,
settings.PIC_RATIO * settings.PIC_WIDTH),
Image.ANTIALIAS)
image_file = io.BytesIO()
image_clean.save(image_file, "PNG")
image_field.file = image_file
# renaming
filename = "{}_pic.png".format(self.object.note.pk)
image_field.name = filename
self.object.note.display_image = image_field self.object.note.display_image = image_field
self.object.note.save() self.object.note.save()
return super().form_valid(form) return super().form_valid(form)