transform POST data before send from Angular to Django (with array of object)
// NOTE: this 2 lines for Django to receive POST data
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
$httpProvider.defaults.transformRequest = function(data) {
if (data === undefined) {
return data;
}
// NOTE: if transform this way -> at Django use json.loads(request.body)
// can support array of object (no need to use getlist() at Django side)
return JSON.stringify(data);
// NOTE: if transform this way -> at Django use request.POST['key']
// array of object will be sent with key like 'rows[10][id]', 'row[10][revenue]'
// need to parse at Django side
// return $.param(data);
}
// NOTE: this 2 lines for Django to receive POST data
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
$httpProvider.defaults.transformRequest = function(data) {
if (data === undefined) {
return data;
}
// NOTE: if transform this way -> at Django use json.loads(request.body)
// can support array of object (no need to use getlist() at Django side)
return JSON.stringify(data);
// NOTE: if transform this way -> at Django use request.POST['key']
// array of object will be sent with key like 'rows[10][id]', 'row[10][revenue]'
// need to parse at Django side
// return $.param(data);
}
Passing Django's CSRF token through AngularJS
option 1:
var csrf_token = $('input[name="csrfmiddlewaretoken"]').val();
$http.post("/import_actual_simple_xls", postData, {
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', "X-CSRFToken" : csrf_token},
}).success(function(data, status, headers, config) {
//other things to do when success
...
});
option 2:
ImportControllers.config(['$httpProvider', function($httpProvider) {
// NOTE: this 2 lines for Django's csrf_token
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
$http.post("/import_actual_simple_xls", postData, {
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', "X-CSRFToken" : csrf_token},
}).success(function(data, status, headers, config) {
//other things to do when success
...
});
ImportControllers.config(['$httpProvider', function($httpProvider) {
// NOTE: this 2 lines for Django's csrf_token
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
AngularJS - Any way for $http.post to send request parameters instead of JSON?
When post data using AngularJS' $http or $http.post(),
at Django side, request.POST is an empty dict but request.body has JSON string.
Use method in this page to transform request data JSON string --> request data parameter,
e.g.
{"param1":"value1","param2":"value2","param3":"value3"} --> param1=value1¶m2=value2¶m3=value3
Set up global transformRequest function:
var app = angular.module('myApp');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
Sample non-global transformRequest per call:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
....});
{"param1":"value1","param2":"value2","param3":"value3"} --> param1=value1¶m2=value2¶m3=value3
Set up global transformRequest function:
var app = angular.module('myApp');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
Sample non-global transformRequest per call:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
....});
For Hidden Field to Send Form Data
use <input name="stock_code" type="hidden" value="{{ actual.code }}">
<input name="stock_code" type="hidden" value="{{ actual.code }}">
Excel File Upload
After spending THE WHOLE DAY surfing internet, trying to find the way to send form data (including uploaded file) from AngularJS front-end to Django backend, here are what I get.jQuery Form is my HERO.
My solution here is
- use jQuery Form to submit form data and file upload to backend.
- use dataType: 'html' for option passed to jQuery Form (I didn't know why but 'xml' didn't work).
- pass callback function to jQuery Form to update models when got response back.
- in the callback function, use $scope.$apply() to force AngularJS refresh its model after posted.
- no progress bar, no upload multiple files here because I don't need it now, but I really appreciate if you could guide me how to do.
NOTE: an example of upload progress here >> http://jquery.malsup.com/form/progress.html
- no progress bar, no upload multiple files here because I don't need it now, but I really appreciate if you could guide me how to do.
NOTE: an example of upload progress here >> http://jquery.malsup.com/form/progress.html
html part (sample form which has both primitive data (multiplier) and file upload (input_excel))
<div id="div_load_xls" class="user-form col-lg-8" ng-app='myApp' ng-controller='importXlsController'>
<form id="frm_load_xls" ng-submit='submitXls()' class="form-horizontal" method="post">
{% csrf_token %}
<input id="id_multiplier" name="multiplier" type="text" />
<input id="id_input_excel" name="input_excel" type="file" />
<input type="submit" name="validate_simple_actual" value="Validate" />
</form>
</div>
Javascript part
<script src='/static/lib/js/angular-1.0.8.js'></script>
<script src='/static/lib/js/jquery.form.js'></script>
<script language="javascript" type="text/javascript">
// get CSRF token from form's hidden field (generated from {% csfr_token %})
var csrf_token = $('input[name="csrfmiddlewaretoken"]').val();
// define AngularJS module and controller
var myAppModule = angular.module('myApp', []);
myAppModule.controller('importXlsController', importXlsController);
// controller definition
function importXlsController($scope, $http) {
// function called when click submit button (ng-submit in the above form)
$scope.submitXls = function() {
// submit options
var options = {
dataType: 'html', // don't know why, but I used 'xml' and it didn't work
url: '/import_actual_simple_xls', // to Django backend
success: $scope.showResponse // callback function to process response defined below
}
// submit form data
$('#frm_load_xls').ajaxSubmit(options);
};
// callback function to process response
$scope.showResponse = function(responseText, statusText, xhr, $form) {
// update model fields
// use $apply to force AngularJS view to refresh
$scope.$apply( function() {
$scope.messages = jQuery.parseJSON(responseText);
});
};
};
</script>
django backend (urls.py omitted)
def import_actual_simple_xls(request):
// read primitive form data
mul = request.POST.get('multiplier', None)
if mul:
messages.append('multiplier = %s' % mul)
else:
messages.append('No multiplier')
// get file uploaded (handle error if needed)
input_excel = request.FILES.get('input_excel', None)
if not input_excel:
messages.append('No Xls')
else:
book = xlrd.open_workbook(file_contents=input_excel.read())
if ('Question List' in book.sheet_names()):
messages.append('xls OK')
else:
messages.append('xls NG')
return JSONResponse(messages)
ไม่มีความคิดเห็น:
แสดงความคิดเห็น