Reputation: 872
I have a function defined in my controller:
def get_config_values():
path = unescape(request.vars['path'])
config = get_config_as_dict(path)
return dict(config)
And in my view I use jQuery $.ajax()
to call it in the view:
$.ajax({
url: "{{=URL('get_config_values.json')}}",
contentType: "application/json; charset=utf-8",
data: {
path: page_path,
},
error: function(x, y, z) {
show_error(x.responseText, y, z);
hide_drawer();
},
success: function(data) {
$('#drawer_content').html(data);
},
type: 'POST',
});
And put simply I cannot get this to work.
type: 'POST'
then the function is called as expected but the path
parameter never makes it through to the controller function (it is just None
)type: 'GET'
web2py decides the function does not exist at all and returns a HTTP 404 (and this remains even if I remove .json
from the URL). No errors in the web2py error log.Web2py seems to behave quite strangely here - to get the POST working in the first place I had to explictly set contentType: "application/json"
otherwise I'd see a 404 there as well, despite the data:'json'
already there.
Has anyone else seen and worked around this behaviour? I don't care if the call is GET or POST, I just want it to work!
Upvotes: 0
Views: 565
Reputation: 25536
There are a few problems. First, when a web2py action returns a dictionary, web2py looks for an associated view to execute (based on the path of the action as well as the extension). In this case, it will look for a view with the path /views/controller_name/get_config_values.json
. If it doesn't find that view, it may attempt to use the generic.json
view, but only if you have explicitly enabled the generic view via response.generic_patterns
(in the scaffolding app, all generic views are enabled by default, but only for local requests). Otherwise, you will get a 404 error (if you inspect the body of the error message in the browser developer tools, you should see a message about an invalid view).
Second, to post JSON via jQuery, you have to convert your Javascript object to a JSON string:
data: JSON.stringify(
{
path: page_path
}
),
With the above, you should now have the value of page_path
in request.vars.path
on the server.
Finally, if you request a .json
URL from web2py, it will set the Content-Type response header to "application/json". However, based on your Javascript code, it appears you want to return HTML (given that you are placing the results into a div on the page). So, you should probably not use the .json
extension in the request (you can also explicitly tell jQuery that the response is HTML by setting dataType: 'html'
).
So, try the following:
$.ajax({
url: "{{=URL('get_config_values')}}",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({
path: page_path,
}),
error: function(x, y, z) {
show_error(x.responseText, y, z);
hide_drawer();
},
success: function(data) {
$('#drawer_content').html(data);
},
type: 'POST',
});
Then either create a get_config_values.html view that generates the desired HTML from the returned dictionary, or otherwise have the get_config_values
function directly return an HTML string.
If you instead do want to return JSON to the browser, then you will need to change your success
callback to process the JSON before attempting to place it in a div.
Upvotes: 2