I'm sure there must be an easy solution for this, but I have been unable to find it. I'm using Python Pyramid in my server and handling requests/responses with AngularJS in Javascript. I'm using the Pyramid HTTP errors to handle some cases, and I'm able to catch them using the Angular http.error() statement.
But this is where I'm stuck, I want to do something with the error messages but if I log the response I just see html code.
In Pyramid this is happening:
if exists:
# continue execution
else:
return HTTPNotFound("The object does not exist")
And in Angular:
$http.get(url)
.success(function(data) {
// do something
})
.error(function(data){
// do something with the error message
});
How would I get that specific error message from the HTTP error? (I'm using JSON as my renderer btw)
Your render is not considered if you do not return a value for renderer but return a response or exception - so do not expect json on the output unless your error handler supports that.
You can do something like this instead:
return HTTPUnprocessableEntity(body=json.dumps(yourobj/string))
And then you can retrieve the JSON in your error handler and use angular.fromJson() to read it.
Maybe a little late, but this might interest other users of Angular:
Simply call a modal to get a pop-up of the Pyramid HTML error:
function(error)
{ console.log("error is: " + error);
var modalInstance = $uibModal.open(
{
template: error,
size:'lg'
});
}
(do not forget to include $uibModal).
Very useful for debugging purposes, but not recommended for production.
Related
Forgive me for stupid questions, but I do not really understand how such relationships work in the Web-development.
I have views.py:
As you can see there is a connection to the api and the information I need is parsed.
Then in my template I have a listener that shows when the user reached the bottom of the page:
As you can see at the bottom of the template i have ajax block where I again connect to api
But now the most important question is this the right way?
Do I need to connect json and fill my arrays and elements in the ajax block one time more? BUT It's all done in views.py.In general, is it realistic to call def main(request) from ajax all the time and append all my arrays and elements automatically? I need like smth this :
$(window).scroll(function () {
if ($(window).scrollTop() + $(window).height() == $(document).height()) {
$.ajax({
url: "{% url 'main' %}",//my request which appends all my arrays automatically
type: "GET",
success: function () {
},
error: function () {
});
Sorry for such questions but I do not understand how such bundles work
As for the counter of connected pages, I'll deal with this later, I need information now in which direction to move in general
It's not a good way. Generally, Django view does not have anything to do with it. You should directly call the URL from ajax and parse the answer in your JS, on the page itself. However, if it is necessary to process the response from that URL in some way, then you should create a separated view that will process the response and return the corresponding JSON as a response.
So the first view only needs to have a template response, and your ajax script on the page should call another view and take over from JSON. This second view sends the request to that remote URL and processes it, then returns JSON as a response.
For this other view, I recommend Django Rest Framework, but this is not necessary if it's a simple feature.
I'm working with a local web application which executes, via AJAX, a Python script on the web-server.
I tried to deploy the application on a remote server and since have been facing an AJAX statusText: "parsererror".
I assume this is because it isn't receiving proper JSON as expected when the script fails. How could I make sure the script interruption returns JSON to the browser, so that I can understand the nature of the error?
The AJAX call is the following:
$.ajax({
async: true,
type: "POST",
url: "cgi-bin/myscript.py",
contentType: "application/x-www-form-urlencoded;charset=ISO-8859-15",
data: JSON.stringify(run_details),
dataType: "JSON"
})
.done(function(data) {
console.log(data)
})
.fail(function(xhr) {
console.log('Error in myscript (cf. Ajax error below).');
console.log('error',xhr);
});
In working conditions, I return data to the client using the following approach, which works well on the local server:
success_message = "Some text"
result = {'message': success_message};
#Send JSON result back to Ajax
print("This line allows the following to be received by browser \n")
json.dump(result, sys.stdout)
In case an error in the script occurs, I call this function to interrupt the script:
def interruptScript(a_cursor, a_conn, error_message):
# Close communication with the database
a_cursor.close()
a_conn.close()
#Add error message to object
result = {'message': error_message};
#Send JSON result back to Ajax
print("This lines allows the following to be received by browser \n")
json.dump(result, sys.stdout)
sys.exit(1)
Ideally, I'd like the error_message to be accessible in AJAX's "responseText" (which is now empty "").
So far, I tried including a string (i.e. sys.exit(error_message)) and a JSON string (i.e. sys.exit(json.dumps(result))) in sys.exit(), but debugging in PyDev I learned that TypeError: an integer is required (got type str), and that this might be a bug. For this reason, I finally added the integer 1, with hope that the json.dump content would be passed via AJAX before the sys.exit.
UPDATE:
I found what was causing the error (a missing python package on the remote server's python install). However I'll keep the question open, because in principle I'm still interested to know how to ensure that the error message from Python (whether from my custom interruptScript() function, or directly from Python informing a package is not installed) gets properly pushed to the browser. I'm using cgitb.enable(), so the question is mostly, how to push the error message if AJAX is expecting JSON?
I'm writing an AJAX function that requests data from my JSON Python webservice. My AJAX request looks like:
url = "http://localhost:8001/blah"
$.ajax({
url: url,
type: 'get',
dataType: 'jsonp',
success: function(data) {
console.log('hi')
}
});
For now, my python web service has a function that handles the request to '/blah' that has the following return statement:
return json.dumps({'a':1, 'b':2 })
My AJAX function is not successfully retrieving a response from my Python Webservice, but I don't get any errors in Firebug. What is my webservice or javascript doing wrong?
What happens when you use Jquery's JSONP datatype, is that a callback function name is sent as a GET param as part of your URL, so you're actually querying something like "http://localhost:8001/blah?callback=json125348274839".
Your response from your web server should look like this:
return "%s({'a':1, 'b':2 })" % _GET_PARAMS('callback')
so your web server will return somthing like "json125348274839({'a':1, 'b':2 })"
Hope that helps!
Zack got it. My javascript was correct. I changed my python return statement to the following:
callback = request.args.get('callback')
return '{0}({1})'.format(callback, {'a':1, 'b':2})
Turn on (or add) logging in your Python web service. Inspect your web server logs... are you receiving the request from your javascript client? Is your web server logging that it is returning a response?
Possibly it depends on the framework that you are using. Is it as simple as returning a string from the handler function? Perhaps the handler is supposed to return a list of strings and, because it is not getting a list, it is returning nothing to the client. Look in your web server logs for errors.
You forgot closing quote and semicolon in the first line =)
If it is not helps, check following:
List item
What are you using as python service? Django, flask, something else? Maybe you can provide provide python code?
Also, look at the 'Net' Firebug's tab and, after ensure that request to 'url' is actually handled (not returned 404 or 50x codes, but 200), check 'Response' sub-tab.
Hope this helps!
Alright, I'm working with a RESTful backend on my project, and submitting data via jquery.
I must say the werkzeug debugger is excellent for debugging specially when you're a terrible python programmer as me. You throw an exception on purpose where you want to investigate, and inspect the code and variables using the html the debugger rendered.
However when you send a post request instead of a get, if you throw an exception on the backend code, of course, the browser won't render the response text.
Is there any technique I can use to render the response text, considering it has javascript and everything?
I'm trying different things such as trying to inject the response text into a popup window, like:
$.postJSON = function(url, data, callback, error_callback) {
return jQuery.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json',
'data': JSON.stringify(data),
'dataType': 'json',
'success': callback,
'error': error_callback
});
};
$.postJSON('/the_uri', {'foo': 'bar'},
function(response) {
var a = 0;
},
function(response) {
var html = response.responseText;
var my_window = window.open('', 'mywindow1', 'width=350,height=150');
$(my_window.document).find('html').html(html);
});
});
But this won't take care of the javascript very well.
Does anyone have any suggestion?
Your approach was nearly correct. I am using the following code to open the response text in a new window (not specific to Werkzeug or Flask at all):
var w = window.open('', 'debug_stuff', 'width=540,height=150');
w.document.open();
w.document.write(response.responseText);
w.document.close();
The last line is the most important. Without it, the code would behave as yours -- it would not execute any JavaScript, because the browser doesn't know the DOM has been fully loaded.
Not javascript, but have you tried to use Firebug, you can use the option for viewing the response in a new tab (Open Response in New Tab).
If you're ready to make some changes on both the client and the server code, you can try this. In your error callback you would re-send the JSON data but as a synchonous form submission. You would create the form using jQuery, give it an input tag and put your JSON in that and submit the form. Something like:
$('<form method="post" style="display:none;">')
.attr('action', 'xxx')
.append(
$('<input>').val(JSON.stringify(data))
).appendTo('body')
.submit();
On the server-side, you would have to accept JSON the regular way when the request's content type is application/json and as form data, eg:
json_string = request.form.get('__json')
if json_string:
data = json.loads(json_string)
I have never tried this but I know the problem you're having and it can waste a lot of time. If you try it I'd like to know how it works out.
Markus' answer works perfectly. thanks so much! this saved me so much hassle.
also consider assigning your handlers to a jqxhr object
http://api.jquery.com/jQuery.post/#jqxhr-object
var jqxhr = $.post(...)
then you would write to your new window
w.document.write(jqxhr.responseText);
For my own education I'm creating a simple daemon that will function as a REST server, listening on socket 9000. For my first test I'm trying to do a REST call of simply doing a GET on http://localhost:9000/getsettings.json.
The simple server I hacked up gets the request OK, but I think there's a problem with the response it's sending. I'm trying to send the response as JSON. The code for the server socket is below. Below that is the jQuery code I'm using to make the JSON request. The print statement in the Python server does print a valid set of settings in JSON format. Neither alert in the Javascript is being called when the page loads. Any ideas?
Python:
def socketThread(self):
while 1:
sock, address = self.serverSocket.accept()
fs = sock.makefile()
line = fs.readline();
if line.startswith('GET /settings.json'):
sock.sendall("HTTP/1.0 200 OK\r\n")
sock.sendall("Content-Type: application/json\r\n")
settings = json.dumps(self.currentSettings) #, indent=4
sock.sendall("Content-Length: " + str(len(settings)) + '\r\n\r\n')
sock.sendall(settings)
print settings
sock.close()
Javascript:
$(document).ready(function() {
$.ajax({
url: 'http://localhost:8080/settings.json',
cache: false,
success: function(json){
alert('json success ' + json);
},
error: function(xhr, textStatus, errorThrown) {
alert(xhr.statusText);
}
});
});
You need to return a 200 OK HTTP response and an empty line before sending your content.
You'll probably need some HTTP headers, too (Content-type would be an obvious one).
I would, however, recommend using one of Python's many HTTP libraries instead of implementing the protocol yourself.
Check that the server is actually being hit (eg, put an import pdb; pdb.set_trace() in your code. I found that jQuery executes the success callback with empty body when the server is not running (or listening on a different port...)
OK, the problem was on the jQuery side, my request was being thwarted by the cross domain origin protection issue - my request was going to localhost on a different port so jQuery wasn't pulling down the data. Now I need to figure out how to make that work. Thanks for the help guys.