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
# SPDX-License-Identifier: GPL-3.0-or-later
import io
from PIL import Image
from django import forms
from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.forms import CheckboxSelectMultiple
@ -77,6 +81,38 @@ class ImageForm(forms.Form):
width = 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):
def clean(self):

View File

@ -55,6 +55,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
/* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */
$("#id_image").change(function (e) {
if (this.files && this.files[0]) {
// Check the image size
if (this.files[0].size > 2*1024*1024) {
alert("Ce fichier est trop volumineux.")
} else {
// Read the selected image file
var reader = new FileReader();
reader.onload = function (e) {
$("#modal-image").attr("src", e.target.result);
@ -62,6 +67,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
}
reader.readAsDataURL(this.files[0]);
}
}
});
/* SCRIPTS TO HANDLE THE CROPPER BOX */

View File

@ -1,10 +1,8 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
import io
from datetime import timedelta, date
from PIL import Image
from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.mixins import LoginRequiredMixin
@ -263,6 +261,7 @@ class PictureUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, FormMixin, Det
return context
def get_success_url(self):
"""Redirect to profile page after upload"""
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.id})
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)
def form_valid(self, form):
"""Save image to note"""
image_field = form.cleaned_data['image']
x = form.cleaned_data['x']
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
image_field.name = "{}_pic.png".format(self.object.note.pk)
self.object.note.display_image = image_field
self.object.note.save()
return super().form_valid(form)