prats
prats

Reputation: 255

Upload File using Angular and Django

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 **

Upvotes: 3

Views: 8370

Answers (4)

Rieven
Rieven

Reputation: 9

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);

Upvotes: 0

GIA
GIA

Reputation: 1706

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})

Upvotes: 3

Ranju R
Ranju R

Reputation: 2557

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.

Upvotes: 1

Sid
Sid

Reputation: 7631

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

Upvotes: -1

Related Questions