Django Crop Image Before Upload using Cropper JS Example

Published On: 27/07/2022 | Category: Django Python


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 Project

In 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 example
Step 2 : Create a App
python3 manage.py startapp cropper
Step 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.py
DATABASES = {  
    '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 Pillow
Step 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.py
from 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 photo
Step 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.py
from 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 Migrations
python 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 migrate
Step 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.py
from 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.py
from 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.py
from 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....