Voici un tutoriel Django pour apprendre à uploader un fichier en AJAX . Dans notre exemple ce sera l' upload d'une image associé à un produit existant. A chaque upload le nom est remplacé par l'id du produit.
Il nous faudra tout d'abord installer la librarie ng-file-upload :
bower install ng-file-upload
Créons ensuite la partie HTML qui traite l'upload:
<div ng-controller="UploadProductImage"> <div style="border:1px dashed #ccc;width:100%;padding:2px;" ngf-drop ngf-select ng-model="files" class="drop-box" ngf-drag-over-class="dragover" ngf-multiple="true" ngf-allow-dir="true" accept="image/*,application/pdf"> <img style="height:100px;" class="img-responsive" src="~{product.image}~" /> </div> <div ngf-no-file-drop>Erreur navigateur</div> </div>
Puis les classes AngularJS :
class UploadProductImage @$inject: ['$scope', 'Upload'] constructor: (@scope, Upload) -> @Upload = Upload @scope.$watch 'files', () => console.log "Un fichier a été ajouté" @upload @scope.files true true upload : (files) => if files and files.length file = files[0] @Upload.upload( url: '/backoffice/upload_product_image', fields: {'id_product': @scope.product.id}, file: file ).progress( (evt) -> progressPercentage = parseInt(100.0 * evt.loaded / evt.total) console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name) ).success( (data, status, headers, config) => console.log('file ' + config.file.name + 'uploaded. Response: ' + data) @scope.product.image = "/media/" + data.filename console.log @scope.customer.image ) app.controller 'UploadProductImage', UploadProductImage
Le routage :
class DashboardController @$inject: ['$scope'] constructor: (@scope) -> @scope.product = {'id' : 1, 'name' : "iMac 2015"} app.controller 'DashboardController', DashboardController
from django.conf.urls import patterns, include, url from django.contrib.auth.decorators import login_required from django.conf import settings from django.conf.urls.static import static urlpatterns = [ url(r'^$', LoginView.as_view()), url(r'^backoffice/upload_product_image$', login_required(UploadImage.as_view())), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
La vue:
from django.views.generic import TemplateView class UploadImage(TemplateView): def post(self, request, **kwargs): id_product = int(request.POST['id_product']) product = Product.objects.get(id=id_product) product.image = request.FILES['file'] product.save() data = { "filename" : product.image.name } return JsonResponse(data)
Et enfin configurons le modèle :
import os from django.db import models from django.utils.deconstruct import deconstructible from django.core.files.storage import FileSystemStorage class OverwriteStorage(FileSystemStorage): def _save(self, name, content): if self.exists(name): self.delete(name) return super(OverwriteStorage, self)._save(name, content) def get_available_name(self, name): return name @deconstructible class PathAndRename(object): def __init__(self, sub_path): self.path = sub_path def __call__(self, instance, filename): f, ext = os.path.splitext(filename) print f, ext if ext not in ['.jpg', '.png', '.jpeg']: raise NameError('Format interdit') new_filename = "{0}{1}".format( instance.id, ext ) return '/'.join(['product', new_filename]) path_and_rename = PathAndRename("") class Product(models.Model): date_add = models.DateTimeField(auto_now_add=True) name = models.CharField(max_length=255) code = models.CharField(max_length=100, null=True) price = models.FloatField() supplier = models.ForeignKey('Supplier', null=True) image = models.ImageField(upload_to=path_and_rename, storage=OverwriteStorage()) def __unicode__(self): return "{0}".format(self.code, )