add support for cropping image. WIP.

This commit is contained in:
Pierre-antoine Comby 2020-03-05 23:32:01 +01:00
parent 13055c393a
commit 08b97e722b
5 changed files with 105 additions and 52 deletions

View File

@ -16,6 +16,7 @@ from django.core.exceptions import ValidationError
from django_tables2.views import SingleTableView from django_tables2.views import SingleTableView
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from dal import autocomplete from dal import autocomplete
from PIL import Image
from note.models import Alias, NoteUser from note.models import Alias, NoteUser
from note.models.transactions import Transaction from note.models.transactions import Transaction
@ -229,8 +230,16 @@ class ProfilePictureUpdateView(LoginRequiredMixin, FormMixin, DetailView):
return self.form_invalid(form) return self.form_invalid(form)
def form_valid(self,form): def form_valid(self,form):
print(form) image_file_field = form.cleaned_data['image']
self.object.note.display_image = form.cleaned_data.get("image","pic/default.png") x = form.cleaned_data['x']
y = form.cleaned_data['y']
w = form.cleaned_data['width']
h = form.cleaned_data['height']
with Image.open(image_file_field.name) as image:
image = image.crop((x, y, w+x, h+y))
image.thumbnail((256, 256), Image.ANTIALIAS)
image.save(image_file_field.name,format=image.format)
self.object.note.display_image = image_file_field
self.object.note.save() self.object.note.save()
return super().form_valid(form) return super().form_valid(form)

View File

@ -3,8 +3,11 @@
from dal import autocomplete from dal import autocomplete
from django import forms from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import os
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.bootstrap import Div from crispy_forms.bootstrap import Div
from crispy_forms.layout import Layout, HTML from crispy_forms.layout import Layout, HTML
@ -27,6 +30,10 @@ class ImageForm(forms.Form):
image = forms.ImageField(required = False, image = forms.ImageField(required = False,
label=_('select an image'), label=_('select an image'),
help_text=_('Maximal size: 2MB')) help_text=_('Maximal size: 2MB'))
x = forms.FloatField(widget=forms.HiddenInput())
y = forms.FloatField(widget=forms.HiddenInput())
width = forms.FloatField(widget=forms.HiddenInput())
height = forms.FloatField(widget=forms.HiddenInput())
class TransactionTemplateForm(forms.ModelForm): class TransactionTemplateForm(forms.ModelForm):

View File

@ -191,3 +191,7 @@ ALIAS_VALIDATOR_REGEX = r''
MEDIA_ROOT=os.path.join(BASE_DIR,"media") MEDIA_ROOT=os.path.join(BASE_DIR,"media")
MEDIA_URL='/media/' MEDIA_URL='/media/'
# Profile Picture Settings
PIC_WIDTH = 200
PIC_RATIO = 1

View File

@ -26,3 +26,4 @@ urlpatterns = [
] ]
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)

View File

@ -2,62 +2,94 @@
{% load i18n static pretty_money django_tables2 crispy_forms_tags %} {% load i18n static pretty_money django_tables2 crispy_forms_tags %}
{% block profile_content %} {% block profile_content %}
<div class="row"> <form method="post" enctype="multipart/form-data" id="formUpload">
<div class="col-sm-4 text-center">
<img class="img-thumbnail" alt="" src="{{user_object.note.display_image.url }}"/>
<p class=""> {% trans "current image" %} </p>
</div>
<div class="col-sm-4 justify-content-center">
<form class=" text-center form my-2" action="" enctype="multipart/form-data" method="post">
{% csrf_token %} {% csrf_token %}
{{ form |crispy }} {{ form |crispy }}
<button class="btn btn-primary mx-2" type="submit"> </form>
{% trans "Change image" %} <!-- MODAL TO CROP THE IMAGE -->
<div class="modal fade" id="modalCrop">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<img src="" id="modal-image" style="max-width: 100%;">
</div>
<div class="modal-footer">
<div class="btn-group pull-left" role="group">
<button type="button" class="btn btn-default" id="js-zoom-in">
<span class="glyphicon glyphicon-zoom-in"></span>
</button> </button>
</form> <button type="button" class="btn btn-default js-zoom-out">
</div> <span class="glyphicon glyphicon-zoom-out"></span>
<div class="col-sm-4"> </button>
<div id="image-holder"></div> </div>
</div> <button type="button" class="btn btn-default" data-dismiss="modal">Nevermind</button>
<button type="button" class="btn btn-primary js-crop-and-upload">Crop and upload</button>
</div>
</div>
</div>
</div> </div>
{% endblock %} {% endblock %}
{% block extracss %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.css" rel="stylesheet">
{% endblock %}
{% block extrajavascript%} {% block extrajavascript%}
<script> <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.js"></script>
// https://codepedia.info/upload-image-using-jquery-ajax-asp-net-c-sharp/ <script src="https://cdn.jsdelivr.net/npm/jquery-cropper@1.0.1/dist/jquery-cropper.min.js"></script>
$("#id_image").on('change', function () { <script>
$(function () {
//Get count of selected files
var countFiles = $(this)[0].files.length;
var imgPath = $(this)[0].value;
var extn = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase();
var image_holder = $("#image-holder");
image_holder.empty();
if (extn == "gif" || extn == "png" || extn == "jpg" || extn == "jpeg") {
if (typeof (FileReader) != "undefined") {
//loop for each file selected for uploaded.
for (var i = 0; i < countFiles; i++) {
/* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */
$("#id_image").change(function (e) {
if (this.files && this.files[0]) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function (e) { reader.onload = function (e) {
$("<img />", { $("#modal-image").attr("src", e.target.result);
"src": e.target.result, $("#modalCrop").modal("show");
"class": "img-thumbnail"
}).appendTo(image_holder);
} }
reader.readAsDataURL(this.files[0]);
image_holder.show();
reader.readAsDataURL($(this)[0].files[i]);
}
} else {
alert("{% trans 'This browser does not support FileReader.' %}");
}
} else {
alert("{% trans 'Please select only images' %}");
} }
}); });
</script>
/* SCRIPTS TO HANDLE THE CROPPER BOX */
var $image = $("#modal-image");
var cropBoxData;
var canvasData;
$("#modalCrop").on("shown.bs.modal", function () {
$image.cropper({
viewMode: 1,
aspectRatio: 1/1,
minCropBoxWidth: 200,
minCropBoxHeight: 200,
ready: function () {
$image.cropper("setCanvasData", canvasData);
$image.cropper("setCropBoxData", cropBoxData);
}
});
}).on("hidden.bs.modal", function () {
cropBoxData = $image.cropper("getCropBoxData");
canvasData = $image.cropper("getCanvasData");
$image.cropper("destroy");
});
$(".js-zoom-in").click(function () {
$image.cropper("zoom", 0.1);
});
$(".js-zoom-out").click(function () {
$image.cropper("zoom", -0.1);
});
/* SCRIPT TO COLLECT THE DATA AND POST TO THE SERVER */
$(".js-crop-and-upload").click(function () {
var cropData = $image.cropper("getData");
$("#id_x").val(cropData["x"]);
$("#id_y").val(cropData["y"]);
$("#id_height").val(cropData["height"]);
$("#id_width").val(cropData["width"]);
$("#formUpload").submit();
});
});
</script>
{% endblock %} {% endblock %}