Django Crop Image Before Upload using Cropper JS Example

Hi Dev,
Now, let's see post of django Crop Image Before Upload using Cropper JS. we will help you to give example of django cropper js example. I explained simply about django crop image before upload. I explained simply step by step crop image using cropper.js django.
Here i explained simply some applications let you upload a profile picture. In addition, it usually also let you crop and resize the image for a better result. Unfortunately, when dealing with image processing we need to install a few dependencies, both in the front-end and in the back-end.
In this example I will demonstrate how to upload an image, display a preview in a modal, crop the image and finally upload it and save in the server.
Step 1 : Create a ProjectIn this step, we’ll create a new django project using the django-admin. Head back to your command-line interface and run the following command:
django-admin startproject exampleStep 2 : Create a App
python3 manage.py startapp cropperStep 3 : Update setting.py
In this step we require to do two things in our settings.py file, One is to change the path of template look up directory. Second one is to configure our media folder. Add the below lines to your settings.py file:
Next, you need to add it in the settings.py file as follows:
.... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'cropper', ] .... MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
And in the urls.py we should edit the configuration like this example/urls.py
from django.conf import settings from django.conf.urls.static import static if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)Step 4 : Database Setup
Next step, we will modify the settings.py file and update the database settings to configure the mydb database:
settings.pyDATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'example', 'USER':'root', 'PASSWORD':'root', 'HOST':'localhost', 'PORT':'3306' } }Step 5 : Install Pillow Library
first of all we need to install a pillow image library throug following below command..
pip install PillowStep 6: Create a Form
In this step we will require the create a formclass for some adding bootstrap class and add button.Open the cropper/forms.py file and add the following code:
cropper/forms.pyfrom django import forms from django.core.files import File from .models import Photo, Employee from PIL import Image # Create your forms here. class PhotoForm(forms.ModelForm): file = forms.ImageField( widget=forms.FileInput( attrs={ "class": "form-control" } )) 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 Meta: model = Photo fields = ('file', 'x', 'y', 'width', 'height', ) def save(self): photo = super(PhotoForm, self).save() x = self.cleaned_data.get('x') y = self.cleaned_data.get('y') w = self.cleaned_data.get('width') h = self.cleaned_data.get('height') image = Image.open(photo.file) cropped_image = image.crop((x, y, w+x, h+y)) resized_image = cropped_image.resize((200, 200), Image.ANTIALIAS) resized_image.save(photo.file.path) return photoStep 7: Create a Model
In this step we will require the database model for storing contacts.Open the cropper/models.py file and add the following code:
cropper/models.pyfrom django.db import models # Create your models here. class Photo(models.Model): file = models.ImageField(upload_to='images/') uploaded_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = 'photo' verbose_name_plural = 'photos'
After creating these model, you need to create migrations using the following command:
Step 8 : Create a Migrationspython manage.py makemigrations
After successfully run the above command go to the cropper/migrations/0001_initial.py
cropper/migrations/0001_initial.py# Generated by Django 3.1.7 on 2022-07-21 10:08 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('core', '0003_photo'), ] operations = [ migrations.AlterField( model_name='photo', name='file', field=models.ImageField(upload_to='images/'), ), ]
Next, you need to migrate your database using the following command:
python manage.py migrateStep 9 : Creating the Views
In this step, we need to create the views for performing fetch record to the database.Open the cropper/views.py file and add:
cropper/views.pyfrom django.shortcuts import render, redirect from .forms import PhotoForm from django.conf import settings from .models import Photo # Create your views here. def photo_list(request): photos = Photo.objects.all() if request.method == 'POST': form = PhotoForm(request.POST, request.FILES) if form.is_valid(): form.save() return redirect('photo_list') else: form = PhotoForm() return render(request, 'photo_list.html', {'form': form, 'photos': photos})Step 10 : Creating the Templates
Here, in this step we need to create a new folder named croppers in the templates folder of croppers.
- base.html
- photo_list.html
Next, open the cropper/templates/base.html file and the add:
cropper/templates/base.html{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Tuts-Station.com</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropper/3.1.3/cropper.min.css" /> </head> <body> <div class="container mt-5"> {% block content %} {% endblock %} </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/cropper/3.1.3/cropper.min.js"></script> {% block javascript %} {% endblock %} </body> </html>
Next, open the cropper/templates/product_create.html file and the add:
cropper/templates/product_create.html{% extends 'base.html' %} {% block content %} <div class="row d-flex justify-content-center"> <div class="col-md-12"> <div class="card"> <div class="card-header"> <h4 class="page-header">Django Cropper Js Crop Image Before Upload Example - <span class="text-primary">Tuts-Station.com</span></h4> </div> <div class="card-body"> <form method="post" enctype="multipart/form-data" id="formUpload"> {% csrf_token %} {{ form }} </form> </div> </div> </div> </div> <!-- FORM TO UPLOAD THE IMAGES --> <!-- MODAL TO CROP THE IMAGE --> <div class="modal fade" id="modalCrop"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title">Crop Image</h4> <button type="button" class="close" data-dismiss="modal">×</button> </div> <div class="modal-body"> <img src="" id="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 js-zoom-in"> <span class="glyphicon glyphicon-zoom-in"></span> </button> <button type="button" class="btn btn-default js-zoom-out"> <span class="glyphicon glyphicon-zoom-out"></span> </button> </div> <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary js-crop-and-upload">Crop and upload</button> </div> </div> </div> </div> <!-- CONTAINER TO DISPLAY THE CROPPED IMAGES --> <div class="row mt-5"> {% for photo in photos %} <div class="col-sm-4 col-md-3"> <img src="{{ photo.file.url }}" class="thumbnail"> </div> {% endfor %} </div> {% endblock %} {% block javascript %} <script> $(function () { /* SCRIPT TO OPEN THE MODAL WITH THE PREVIEW */ $("#id_file").change(function () { if (this.files && this.files[0]) { var reader = new FileReader(); reader.onload = function (e) { $("#image").attr("src", e.target.result); $("#modalCrop").modal("show"); } reader.readAsDataURL(this.files[0]); } }); /* SCRIPTS TO HANDLE THE CROPPER BOX */ var $image = $("#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 %}Step 11 : Creating URLs
In this section, we’ll create the urls to access our views.Go to the urls.py cropper/urls.py file and update it as follows:
cropper/urls.pyfrom django.urls import path from .views import photo_list urlpatterns = [ path('photo-list/', photo_list, name="photo_list"), ]
Next, we will require the modify the urls.py your root preoject folder lets update the file.
example/urls.pyfrom django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('', include('cropper.urls')), ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)Run the Server
In this step, we’ll run the local development server for playing with our app without deploying it to the web.
python manage.py runserver
Next, go to the http://localhost:8000/photo-list/ address with a web browser.
Preview:

I Hope It will help you....