1

Hi I have a web app using AngularJS as the frontend and Django Rest Framework as the backend. Everything works smoothly except that when I pass a json value inside the data parameter of the upload function of ngFileUpload and print the request.data inside the django rest framework it results to

{ 'principal_master[id]': ['1'], 'file': [<InMemoryUploadedFile: adgc.jpg (image/jpeg)>], 'username': ['dsadasd'] }

When it should result to

{ 'principal_master' : '{ "id": "1"}', 'file': [<InMemoryUploadedFile: adgc.jpg (image/jpeg)>], 'username': ['dsadasd']  }

Here is my code on the front end HTML:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script type="text/javascript" src="https://angular-file-upload.appspot.com/js/ng-file-upload.min.js"></script>
<div ng-controller="MyCtrl">
    <form name="myForm" >
        <fieldset>
          <legend>Upload on form submit</legend>
          Username:
          <input type="text" name="userName" ng-model="username" size="31" required>
          <i ng-show="myForm.userName.$error.required">*required</i>
          <br>Photo:
          <input type="file" ngf-select ng-model="picFile" name="file"    
                 accept="image/*" ngf-max-size="2MB" required
                 ngf-model-invalid="errorFile">
          <i ng-show="myForm.file.$error.required">*required</i><br>
          <i ng-show="myForm.file.$error.maxSize">File too large 
              {{errorFile.size / 1000000|number:1}}MB: max 2M</i>
          <img ng-show="myForm.file.$valid" ngf-thumbnail="picFile" class="thumb"> <button ng-click="picFile = null" ng-show="picFile">Remove</button>
          <br>
          <button ng-disabled="!myForm.$valid" 
                  ng-click="uploadPic(picFile)">Submit</button>
          <span class="progress" ng-show="picFile.progress >= 0">
            <div style="width:{{picFile.progress}}%" 
                ng-bind="picFile.progress + '%'"></div>
          </span>
          <span ng-show="picFile.result">Upload Successful</span>
          <span class="err" ng-show="errorMsg">{{errorMsg}}</span>
        </fieldset>
        <br>
    </form>
</div>

Here is my code on the front end JS: var app = angular.module('myApp', ['ngFileUpload']); app.config(function($interpolateProvider, $httpProvider) { // Change template tags $interpolateProvider.startSymbol('[['); $interpolateProvider.endSymbol(']]'); });

app.controller('MyCtrl', function($scope, Upload, $timeout){
    $scope.uploadPic = function(file) {
    file.upload = Upload.upload({
      url: 'http://192.168.0.50:8000/api/people/v1/principals/add/',
      data: {username: $scope.username, principal_master : '{ "id": "1"}' file: file},
    });

    file.upload.then(function (response) {
      $timeout(function () {
        file.result = response.data;
      });
    }, function (response) {
      if (response.status > 0)
        $scope.errorMsg = response.status + ': ' + response.data;
    }, function (evt) {
      // Math.min is to fix IE which reports 200% sometimes
      file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
    });
    }
});

Here is my basic code on the back-end:

#python
import json

#Django Core
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.db.models import Q

#Rest Framework
from rest_framework.parsers import FileUploadParser, FormParser, MultiPartParser
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view, parser_classes

#test_people app
from .serializers import *
from test_people.decorators import token_required

@api_view(['POST'])
# @parser_classes((FileUploadParser,))
@parser_classes((FormParser, MultiPartParser))
@csrf_exempt
@token_required
def add(request):
    #print(request.data)
    if request.method == 'POST':
        print("-------------")
        print(request.data)
        print(request.data['principal_master'])
        print(type(request.data['principal_master']))
        return
4
  • why do you have json string for id instead of the actual object. Commented Mar 22, 2016 at 14:54
  • Because that key's value is another serializer for inheritance and DRY purposes Commented Mar 23, 2016 at 3:08
  • What your request look like in the network tab of your browser? Commented Mar 28, 2016 at 7:38
  • This one: { 'principal_master[id]': ['1'], 'file': [<InMemoryUploadedFile: adgc.jpg (image/jpeg)>], 'username': ['dsadasd'] } Commented Mar 28, 2016 at 8:21

1 Answer 1

1

I could solve this using the arrayKey: '' update option, and MultiPartParser.

My controller:

Upload.upload({
  url: '/my/api/file/',
  data: {
      file: file
  },
  arrayKey: '',
}, ...)

My view:

class FileViewSet(viewsets.ModelViewSet):
    queryset = File.objects.all()
    serializer_class = FileSerializer
    parser_classes = (parsers.FormParser, parsers.MultiPartParser,)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.