3

So, I have a issue that i cant find a solution for. I am developing an application using Django where my front end has to be in angular-js. Now I am able to render forms and also post the data from the forms, but i have no idea how to upload a file using these forms.

This is my code:

in urls.py

url(r'^getter/$', TemplateView.as_view(template_name = "upload.html"))
url(r'^getter/test/', views.test, name = "thanks.html")

in views.py

def test(request):
   upload_form = uploadform(request.POST, request.FILES)
   data = json.loads(request.body)
   file_path = data.path

in forms.py

select_file = forms.FileField(label = "Choose File")

in my js file inside my controller

myapp.controller('abc', function ($scope, $http)
$scope.submit = function(){
var file = document.getElementById('id_select_file').value
var json = {file : string(file)}
$http.post('test/',json)
...success fn....
...error fn...

}; });

Now the issue is that if in my view if i do

f = request.FILES['select_file']

I get error 'select_file' not found in MultiValueDict: {}

probably the issue is that with the way am sending my post request am not sending all the meta data....please help me out with this i have spent the whole day looking for a solution but no avail.

PS: for some restriction policies I can not use Djangular so please give me solutions that donot use djangular. Thanks

Edit: **Applying file properties to the json that the server is receiving doesnt work either **

prats
  • 225
  • 5
  • 15
  • Don't know Django, but your json uses `file` and your view refers to `select_file` Is this correct? – craigb Jul 26 '14 at 05:02
  • @craigb yeah just edited my question. basically none od django's file methods or functions work when i use angular – prats Jul 26 '14 at 05:22

4 Answers4

3

I was having the same problem. I found an efficient solution of how to send files to Django Forms with Angular $http.

DIRECTIVE

app.directive("filesInput", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});

HTML

<form ng-submit="send()" enctype="multipart/form-data">
    <input type="text" ng-model="producer.name" placeholder="Name">
    <input type="file" files-input ng-model="producer.video">
</form>

CONTROLLER

$scope.send = function(){
    var fd = new FormData();
    fd.append('video', $scope.producer.video[0]);
    fd.append("name", $scope.producer.name);

    $http({
        method: 'POST',
        url: '/sendproducer/',
        headers: {
          'Content-Type': undefined
        },
        data: fd,
        transformRequest: angular.identity
    })
    .then(function (response) {
      console.log(response.data)
    })
}

DJANGO VIEW FORM

class ProducerView(View):

    def dispatch(self, *args, **kwargs):
        return super(ProducerView, self).dispatch(*args, **kwargs)

    def post(self, request):
        form = ProducerForm(data = request.POST, files = request.FILES or None)
        if form.is_valid():
            form.save()
            return JsonResponse({"status": "success", "message": "Success"})
        return JsonResponse({"status": "error", "message": form.errors})
GIA
  • 1,400
  • 2
  • 21
  • 38
1

Use the below snippet so that you can send usual data along with the file data from angular to django.

$scope.submit = function(){
    var fd = new FormData();
    datas = $("#FormId").serializeArray();
    // send other data in the form
    for( var i = 0; i < datas.length; i++ ) {
         fd.append(datas[i].name, datas[i].value);
        };
    // append file to FormData
    fd.append("select_file", $("#id_select_file")[0].files[0])
    // for sending manual values
    fd.append("type", "edit");
    url = "getter/test/",
    $http.post(url, fd, {
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success(function(data, status, headers, config) {
        // this callback will be called asynchronously
        // when the response is available
    }).
    error(function(data, status, headers, config) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
        });
};

Now you will get select_file under request.FILES and other datas inside request.POST in your django view.

Ranju R
  • 2,407
  • 21
  • 16
  • I tried the above snippet and it was working fine for me. I am not sure why it got down vote. It will be great if you can point-out the issue with this. Thanks! – Ranju R Nov 04 '16 at 13:06
0

A combination of early posts with the correct Angular functions.

(function(app){
   app.controller("Name_of_Controller", function($scope, $http){
      $scope.submit = function(){
         var fd = new FormData();
         datas = $("#formID").serializeArray();
         for( var i = 0; i < datas.length; i++ ) {
            fd.append(datas[i].name, datas[i].value);
         };
        fd.append("selected_file", $("#file_id")[0].files[0])
        fd.append("type", "edit");
        url = "/results/",
        $http.post(url, fd, {
            headers: {'Content-Type': undefined },
            transformRequest: angular.identity
        }).then(function (response) {
            console.log(response.data)
        }).catch(function (err) {});;
    };
});
})(App_name);
Rieven
  • 9
  • 1
-1

I strongly suggest using a third party plugin such as ngUpload or fileUploader to achieve this. What you are doing on the client does not look correct.

Also refer to this SO thread on angularjs file uploads

Community
  • 1
  • 1
Sid
  • 7,511
  • 2
  • 28
  • 41
  • is there no way that we can use the file upload features of django while posting data using angular? Django File upload is simple and clean... – prats Jul 26 '14 at 04:56