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:
commit
fcd1bb98a8
@ -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):
|
||||||
|
@ -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 %}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user