Hey les amis !
Voici un petit tips rapide pour gérer l’upload de fichier avec AngularJS en front et Django-Rest-Framework en back.
C’est assez simple quand on a toutes les cartes en main (et j’ai galéré pour toutes les avoir ces foutus cartes :D).
Alors côté AngularJS j’utilse la bibliothèque ng-file-upload. L’installation est simple comme bo…wer !
$ bower install ng-file-upload --save
Il y a ensuite 3 parties. La vue HTML, la gestion JS et le back en DRF.
Pour l’exemple on partira sur le principe d’uploader seulement un fichier
Formulaire HTML
<div ng-controller="ProfileDocumentsCtrl"> <form ng-submit="submitForm($event);"> <input type="file" ngf-select="onFilesSelected($files, $invalidFiles)"> <button type="submit">Envoyer</button> </form> </div>
Le traitement JS
var app = angular.module('ACoolApp', ['ngFileUpload']) app.controller('UploadCtrl', ['$scope', 'Upload', function ($scope, Upload) { $scope.file = {}; // Le fichier que l'on veut envoyer $scope.onFilesSelected = function (files, invalidFiles) { // Lors de la selection d'un fichier on met à jour // $scope.file avec la nouvelle sélection $scope.file = files[0]; }; $scope.submitForm = function (event) { event.preventDefault(); Upload.upload({ url: 'http://monapi.com/api/upload/fichier', file: $scope.file, // Pour envoyer un fichier avec Django-Rest-Framework // il faut du PUT et pas du POST method: 'PUT' }).then( function (resp) { console.log(resp); }, function (resp) { console.log(resp); }, function (evt) { $scope.file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total)); console.log($scope.file.progress); }); } }]);
Le traitement DRF
Commencons par avoir un modèle, et ensuite un serializer pour traiter notre fichier
### Model ### def document_folder(instance, filename): """ Cette fonction permet de générer un nom unique avec la date au début de celui-ci. Toujours pratique d'avoir la date au début ! On en profite pour séparer les fichiers par utilisateur """ filename = '{}-{}.{}'.format(datetime.today().replace(microsecond=0), uuid.uuid4().hex, filename.split('.')[-1]) return 'documents/{}/{}'.format(instance.user_id, filename) class Document(models.Model): """ On part sur un modèle simple, un fichier lié à un utilisateur """ user = models.ForeignKey(User) file = models.FileField(upload_to=document_folder) ### Serializer ### class DocumentsCreateSerializer(serializers.ModelSerializer): class Meta: model = Document fields = ('file',)
Maintenant que l’on a tous les éléments en main, on peut faire l’action API qui va s’occuper
de l’upload
@api_view(['PUT']) # On oublie pas de mettre en PUT @parser_classes((MultiPartParser,)) @permission_classes((IsAuthenticated,)) @csrf_exempt def upload_document(request): s = DocumentsCreateSerializer(data=request.data) if s.is_valid(): s.save(profile=request.user) # C'est ici que l'on ajoute l'utilisateur return Response({'detail': s.data}) return Response({'detail': s.errors}, status=status.HTTP_400_BAD_REQUEST)
Et voilà, on y est. L’upload est fonctionnel. Alors ici nous avons un exemple basique évidemment. ng-file-upload permet une gestion fine de l’upload, de gérer de la validation pre-upload, etc…
J’vous laisse vous amuser avec ça 😉
Tchuss