Register App myapp
devproject/settings.py
//devproject/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', #add myapp ]Creating View
myapp/views.py
//myapp/views.py from django.shortcuts import render from .forms import ImageForm from django.http import JsonResponse def index(request): form = ImageForm(request.POST or None, request.FILES or None) if form.is_valid(): form.save() return JsonResponse({'message': 'works'}) context = {'form': form} return render(request, 'main.html', context)devproject/urls.py
//devproject/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('myapp.urls')) ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)myapp/urls.py
//myapp/urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\django\devproject>python manage.py makemigrations
C:\django\devproject>python manage.py migrate
myapp/models.py
//myapp/models.py from django.db import models class Image(models.Model): file = models.ImageField(upload_to='images') uploaded = models.DateTimeField(auto_now_add=True) def __str__(self): return str(self.pk)myapp/forms.py
//myapp/forms.py from django import forms from .models import Image class ImageForm(forms.ModelForm): class Meta: model = Image fields = ('file',)Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css
Jquery
https://jquery.com/download/
CDN : jsDelivr CDN
https://www.jsdelivr.com/package/npm/jquery
https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
Cropper
A simple jQuery image cropping plugin.
https://fengyuanchen.github.io/cropper/
CDN : https://cdnjs.com/libraries/cropper
myapp/templates/home.html
//myapp/templates/home.html {% extends 'base.html' %} {% block content %} <div class="container py-5"> <header class="text-white text-center"> <h1 class="display-4">Python Django Image Crop and Upload Crop Image with javascript ajax</h1> </header> <div class="row py-4"> <div class="col-lg-6 mx-auto"> <div class="input-group mb-3 px-4 py-2 rounded-pill bg-white shadow-sm"> <form action="" id="image-form" style="padding-top:10px;"> {% csrf_token %} {{form.as_p}} </form> </div> <div id="alert-box"></div> <div class="image-area mb-3"><div id="image-box"></div></div> <button class="btn btn-primary mt-3 not-visible" id="confirm-btn">Confirm</button> </div> </div> </div> <style> #upload { opacity: 0; } .image-area { border: 2px dashed rgba(255, 255, 255, 0.7); padding: 1rem; } body { min-height: 100vh; background-color: #7b9a75; background-image: linear-gradient(147deg, #7b9a75 0%, #d7dde8 100%); } </style> {% endblock content %}myapp/templates/base.html
//myapp/templates/base.html {% load static %} <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/> <!-- jquery --> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> <!-- cropper --> <script src="https://cdnjs.cloudflare.com/ajax/libs/cropper/4.1.0/cropper.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropper/4.1.0/cropper.min.css"> <title>Python Django Image Crop and Upload Crop Image with javascript ajax</title> <style> .not-visible { display: none; } </style> </head> <body> <div class="container"> {% block content %} {% endblock content %} </div> <script> const alertBox = document.getElementById('alert-box') const imageBox = document.getElementById('image-box') const imageForm = document.getElementById('image-form') const confirmBtn = document.getElementById('confirm-btn') const input = document.getElementById('id_file') const csrf = document.getElementsByName('csrfmiddlewaretoken') input.addEventListener('change', ()=>{ alertBox.innerHTML = "" confirmBtn.classList.remove('not-visible') const img_data = input.files[0] const url = URL.createObjectURL(img_data) imageBox.innerHTML = `<img src="${url}" id="image" width="700px">` var $image = $('#image') console.log($image) $image.cropper({ aspectRatio: 16 / 9, crop: function(event) { console.log(event.detail.x); console.log(event.detail.y); console.log(event.detail.width); console.log(event.detail.height); console.log(event.detail.rotate); console.log(event.detail.scaleX); console.log(event.detail.scaleY); } }); var cropper = $image.data('cropper'); confirmBtn.addEventListener('click', ()=>{ cropper.getCroppedCanvas().toBlob((blob) => { console.log('confirmed') const fd = new FormData(); fd.append('csrfmiddlewaretoken', csrf[0].value) fd.append('file', blob, 'my-image.png'); $.ajax({ type:'POST', url: imageForm.action, enctype: 'multipart/form-data', data: fd, success: function(response){ console.log('success', response) alertBox.innerHTML = `<div class="alert alert-success" role="alert"> Successfully saved and cropped the selected image </div>` }, error: function(error){ console.log('error', error) alertBox.innerHTML = `<div class="alert alert-danger" role="alert"> Ups...something went wrong </div>` }, cache: false, contentType: false, processData: false, }) }) }) }) </script> </body> </html>Run : C:\django\devsite>python manage.py runserver