Send data by post from AngularJs to Django - angularjs

I want to send data from AngularJS to the back end (Django) via Http request.
I tried many ways but I keep not getting the sent data when receiving the request in django.
Before I paste my code, I just have changed the configurations in AngularJS in my project as the following
var myApp = angular.module('myApp',[]).config(['$httpProvider', '$interpolateProvider', function ($httpProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('{/');
$interpolateProvider.endSymbol('/}');
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';}]);
The urls:
urlpatterns = [
url(r'^save_comment/', views.save_comment, name='save_comment'),]
Sending Https POST in Angular:
$scope.submit_comment = function () {
$http({
method: "POST",
url: 'save_comment',
data: $.param({
'fish_id' : "1"
})
}).success(function (response) {
console.log(response.result);
}).error(function () {
console.log("failed")
}); }
Receiving the request in the Views
def save_comment(request):
data = request.POST.get('fish_id')
return JsonResponse({'result': data}, content_type="application/json", safe=False)
But I didn't get any result. the console gave me this error:
POST http://127.0.0.1:8000/brain_browser/save_comment 500 (Internal
Server Error)
So what should I do to send Post data from Angular to Django?
Thank in a dvance.

Not an answer but you can debug yourself. Add this to settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': True,
},
},
}

Your url: 'save_comment' seems to be missing a slash at the beginning, since your url expects http://127.0.0.1:8000/save_comment/ but because of the missing slash you are sending http://127.0.0.1:8000/brain_browser/save_comment.
So change the url in your Javascript to url: '/save_comment/'
Edit: #bobleujr's answer could also fix the problem if csrf tokens are the problem. In my personal Angular/Django project I simply put this at the very top of my javascript:
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
2nd Edit: This should be the solution
In your views, do this instead of data = request.POST.get('fish_id'):
body_unicode = request.body.decode('utf-8')
data = json.loads(body_unicode)
# Work with "data" from now on, i.e:
print(data["fish_id"])
This is because request.body (Your parameters) is a byte string, and json.loads does not accept byte strings.
Also make sure you have json imported in your views at the very top like so:
import json

Related

CORS and Angular $http GET to Google Places API

New to angular, trying to setup a very simple application using the Google Maps / Places API.
I can successfully use the geolocation service with:
.controller('MainCtrl', [
'$scope',
'$http',
function($scope, $http){
$scope.userLocation = [];
$scope.currentLocation = function() {
$http({
method: 'GET',
url: 'https://www.googleapis.com/geolocation/v1/geolocate?key=xxx'
}).then(function successCallback(response) {
$scope.userLocation.push(response);
});
}
}])
Problem:
When I try a similar GET request to their Places API - I get CORS errors:
XMLHttpRequest cannot load https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=36.23…5.1458888&type=bar&key=xxx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://0.0.0.0:3000' is therefore not allowed access.
Question: Am I able to make these types of requests from Angular or do I need to setup the backend to make that call instead?
I tried using JSONP as the method, which passed the CORS issue, but then I have the problem of not being able to access the data. Not sure if it's invalid JSON... but it says Unexpected identifier :, and when I view the source it looks like perfectly fine data to me:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 36.2388477,
"lng" : -115.1540073
},
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
"id" : "578bfba1f17b0c5fbdafd5b71600b50d3e95c1ca",
"name" : "Ruby Tuesday",
"opening_hours" : {
"open_now" : true,
"weekday_text" : []
},
You can use Places API on client side via the library included in Google Maps JavaScript API.
Please refer to this page to figure out how it works:
https://developers.google.com/maps/documentation/javascript/places
Otherwise, you have to create your backend server to send requests to Google and pass response to your client side code.
Hope it helps!
After research I found the below solution. It worked on angular 11.
Some google get api gives CORS issues so to resolve that you need to install below npm package
npm install axios
In the sevice.ts file
const axios = require('axios');
getTimeZone(latitude: any, longitude: any): any {
console.log("lat", latitude);
const url1 =
`https://maps.googleapis.com/maps/api/timezone/json?location=` +
latitude +
"," +
longitude +
`&timestamp=1331161200&key=` +
this.googleApiKey;
const config = {
method: "get",
url: url1,
headers: {},
};
return new Observable<any>((observer) => {
axios(config)
.then(function (response: any): void {
observer.next(response.data);
// return response.data;
})
.catch(function (error: any): void {
observer.next(error);
});
});
}
in component.ts file
getTimezoneVal(lat: any, long: any): void {
this.lat = lat;
this.long = long;
this.googleAddressService.getTimeZone(lat, long).subscribe(
(res: any) => {
console.log("res", res);
})
}
In component file you will get response and CORS issue will get resolved....
Thanks....
Vikas Anand
I think JSONP may work in this situation, Jsonp helps for cross domain issues.

Angular posts whole data to Django view as key in QueryDict

I am using Angular 1.4.4 and Django 1.8. When i post data from Angular to Django view it comes in the form of whole data as key in the QueryDict.
So in view in debug mode when i evaluate request.POST it returns this
<QueryDict: {u'{"messagetitle":"","value":"","valueam":"","wrong_response":"","stop":"","messagekind":"1","undefined":"","messagetype":"3","state":"","language_id":1}': [u'']}>
Notice posted data is inside u'' as key and its value is [u'']
Angular dataservice code is this
function createDraft(data) {
return $http({
url: view_url + 'create_draft/',
method: 'POST',
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
}
Controller code
app.controller('message',function($scope, $ngBootbox, dataservice, $http){
$scope.formData = {
"messagetitle":"", "value":"", "valueam":"",
"wrong_response": "", "stop": "", "messagekind": "1",
"undefined_response": "", "messagetype":"3",
"state": "", "language_id":1
};
saveDraft = function(){
dataservice.createDraft($scope.formData).then(
function(res) {
$ngBootbox.alert("<div class='alert-success alert_box'>Draft Saved</div>")
},
function(res) {
var error_message = res['statusText'].trim();
if (error_message === '')
error_message = 'Error Occurred';
$ngBootbox.alert("<div class='alert-warning alert_box'>" + error_message + "</div>")
})
}
saveDraft function is called from angular template(which is html form) on button click.
Let me know what i am doing wrong here. I have tried some answers on stackoverflow but could not find any question/answer which addresses my specific problem.
PS:
I know i can do json.loads(request.body) but i need to post data in django's request.POST
Use $.param(data) instead of data in your service

Angular $http read String?

The back end guy wants to send me a string, which will be returned by $http.post. If he sends me something like "success", I will get error like "parsing Json failed". I want him to wrap the string into object like "{"message": "success"}", which works fine. But other back end guys say that front end should comply with back end, so they will just send me the string. Is there any way that I can read the string?
This is the code I use if he sends me "{"message": "success"}", which works perfectly:
AdminService.saveCache(cache)
.then(function(data) {
var data = data.data;
if (data.message == "success") {
scope.successMessage = "Cache hours saved successfully";
} else {
scope.errorMessage = data.message;
}
}, function() {
scope.errorMessage = "Submission failed";
});
By default angular tries to detect if a http response contains JSON. Sometimes this detection fails and you get such an error as you described in your question.
You can avoid this behavior for a single request if you override the response transformation by providing an transformResponse property for on the configuration object passed to the request:
$http({
url: '...',
method: 'POST',
//Just return original response from server without parsing
transformResponse: [function (data, headers) {
return data;
}];
});
Alternatively you can change the default behavior for all your app's http requests by overriding the default response transformation:
myApp.config('$httpProvider', function($httpProvider) {
$httpProvider.defaults.transformResponse = [function (data, headers) {
return data;
}];
}]);
For more information see API Reference $http section "Transforming Requests and Responses"
the API Response Content-Type should be set to text/plain; and use POSTMAN to verify, it would save you a lot of headache

AngularJS Response does not match configured parameter

I've got a problem with service configuration. I want to display one user by this function:
$scope.findOne = function() {
$scope.user = Users.get({
userId: $stateParams.userId
});
};
But I am in trouble with User service :( I don't know, how should I change my the code to avoid angular error:
Error in resource configuration for action object. Expected response
to contain an array but got an {2}
Here is a code of my actual working service (without function findOne working of course:))
'use strict';
angular.module('users').factory('Users', ['$resource',
function($resource) {
return $resource('users', {}, {
update: {
method: 'PUT'
},
remove: {
method: 'DELETE',
url: 'users/:id',
params: {id: '#_id'}
}
});
}
]);
At a guess, I'd say your users API endpoint is expecting /users/:userId for GET requests. Your code at the moment will request /users?userId=nnn. You need to add an action for get with the ID in the URL, eg
return $resource('users', {id: '#userId'}, {
get: {
method: 'GET',
url: 'users/:id',
isArray: false
},
// etc
You can also make users/:id the default URL as long as it doesn't interfere with your other action configurations.

Restangular save and retry after refresh

I'm working on an SPA that is usually online but can go offline and I have to keep a log of all requests to an API. When certain requests fail I should retry them later.
I've got a local DB to save all requests. When my app starts I retrieve them all and retry the ones marked to.
What I need is a way to config a Restangular object based on what I already sent. I have a response interceptor and I'm saving the restangular response object.
{
config: {
headers: Object,
method: "GET",
params: Object,
transformRequest: Array[1],
transformResponse: Array[1],
url: "..."
},
data: {...},
headers: {...},
status: 200,
statusText: "OK"
}
Is there a function to create a Restangular with the given config object?
Thanks
If i would doing this i would setup setErrorInterceptor
var yourLocalDb = function($http) {
var failedRequests = [];
this.store = function(request) {
this.failedRequests.push(request);
}
this.retry = function() {
var self = this;
angular.forEach(this.failedRequests,function(request) {
$http(request.response.config).then(function() {
//in case of success
self.failedRequests.splice(self.failedRequests.indexOf(request),1);
request.responseHandler.apply(undefined,arguments);
}), request.deferred.reject);
});
}
}
Restangular.setErrorInterceptor(function(response, deferred, responseHandler) {
yourLocalDb.store({
response : response,
responseHandler : responseHandler,
deffered : deffered
});
}
then when you have connection you can just call
yourLocalDb.retry();
Not tested, but it should give you clue.

Resources