Uploader un fichier avec AngularJS et Django Rest Framework

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

Aymeric DERBOIS

J'ai 27 ans et je suis développeur. Je travail la plupart du temps sur des techno web, mais pas que. Étant à l'affût des nouveautés, j'adore découvrir tout et n'importe quoi dans l'informatique. Je suis amoureux de CakePHP et j'utilise au quotidien Django. Je suis très ouvert d'esprit :). J'aime bien utiliser AngularJS aussi de temps à autre pour faire du front. Au quotidien j'utilise Fedora/Ubuntu pour le desktop et CentOS pour mes serveurs. Par ailleurs je maîtrise le C/C++/Python/PHP/...

More Posts - Website

Follow Me:
Twitter

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.