Reputation: 255
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
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
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
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
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