Latest Chrome caching ajax response despite no cache headers - django

I have a simple form in a modal that gets populated by a ajax request (to a server running Django)
If I add choices to a choice field, those choices are not displaying for a few minutes on the modal. This issues only appeared after updating to the latest version of chrome (80.3987.149).
I am including no-cache headers in the ajax response like this:
response['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response['Pragma'] = 'no-cache'
response['Expires'] = '0'
But it doesn't seem to matter.
My ajax call method looks like this:
openAlertModalOnclick(e) {
e.preventDefault();
let self = this;
$.get($(e.target).attr("href"), resp => {
$("#alertModal").html(resp.html).foundation("open").foundation();
})
}).fail(() => {
this.showErrorToast("Error occurred while loading alerts.")
})
}
I am 90% sure this is an issue with just the latest version of chrome, as I could not reproduce it until I updated chrome. Is there anything else I can do to get chrome to stop caching the form?

The solution was the change the $.get call to $.ajax and pass in a cache: false parameter.
The function to open the modal now looks like this:
openForm52AlertModalOnclick(e) {
e.preventDefault();
let self = this;
SpinnerController.showSpinner();
$.ajax({
url: $(e.target).attr("href"),
method: 'GET',
cache: false,
success: function (resp) {
$("#alertModal").html(resp.html).foundation("open").foundation();
},
error: function () {
this.showErrorToast("Error occurred while loading alerts.")
},
});

Related

flask endpoint for ajax call

I'm making an ajax call to my server while pressing submit button.
Button is present in page http://127.0.0.1:5000/post/15.
Jquery function invoked and the endpoint definition for submit_comment in python respectively:
function submit_comment(post_id) {
var uname = $('input[name="uname"]').val();
var comment = $('textarea[name="comment"]').val();
$.ajax({
url: "/submit_comment",
data: {name: uname, comment: comment, post_id: post_id},
method: "POST",
datatype: 'json',
success: function(response) {
console.log('reaches here');
addElement(response);
console.log('Is it me');
},
error: function(error) {
console.log('reached Error');
console.log(error);
}
});
}
py
#main.route('/submit_comment', methods = ['POST', 'PUT'])
def submit_comment():
entry = request.get_json(force=True)
print 'comment:', entry
....
Main is the blueprint. But I'm getting following 404 error.
127.0.0.1 - - [24/Aug/2017 10:30:55] "POST /post/submit_comment HTTP/1.1" 404 -
I am wondering from where this post got appended into the endpoint.
Can someone help me to understand the error and resolve it?
Thanks,
Deepak
I don't know a lot, but I know that the Flask docs on ajax say to query for the script root like this:
$SCRIPT_ROOT = {{ request.script_root|tojson }};
and then use that as part of the request URL.
An example from an ajax call I've used ($.getJSON being a jquery function for $.ajax)
$.getJSON($SCRIPT_ROOT + '{{ url_for("help_email") }}',

Fetch API for Django POST requests

I'm trying to remove jQuery from a React/Redux/Django webapp and replace the $.ajax method with the Fetch API. I've more or less got all my GET requests working fine and I seem to be able to hit my POST requests, but I cannot seem to format my request in such a way as to actually get my POST data into the Django request.POST object. Every time I hit my /sign_in view, the request.POST object is empty. My entire app's backend is built around using Django forms (no Django templates, just React controlled components) and I would really like to not have to rewrite all my views to use request.body or request.data.
Here is all the code I can think that would be relevant, please let me know if there's more that would be helpful:
This is the curried function I use to build my full POST data and attach the CSRF token:
const setUpCsrfToken = () => {
const csrftoken = Cookies.get('csrftoken')
return function post (url, options) {
const defaults = {
'method': 'POST',
'credentials': 'include',
'headers': {
'X-CSRFToken': csrftoken,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
const merged = merge(options, defaults)
return fetch(url, merged)
}
}
export const post = setUpCsrfToken()
This is the API method I use from my React app:
export const signIn = data => {
return post('/api/account/sign_in/', data)
}
The data when it is originally packaged up in the React app itself is as simple as an object with string values:
{
email: 'email#email.com',
password: 'password
}
I've looked at these questions and found them to be nominally helpful, but I can't figure out to synthesize an answer for myself that takes into account what I assume is some of the intricacies of Django:
POST Request with Fetch API?
Change a jquery ajax POST request into a fetch api POST
Convert JavaScript object into URI-encoded string
Is there a better way to convert a JSON packet into a query string?
Thanks!
You have to set the appropriate X-Requested-With header. jQuery does this under the hood.
X-Requested-With: XMLHttpRequest
So, in your example, you would want something like:
const setUpCsrfToken = () => {
const csrftoken = Cookies.get('csrftoken')
return function post (url, options) {
const defaults = {
'method': 'POST',
'credentials': 'include',
'headers': new Headers({
'X-CSRFToken': csrftoken,
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest'
})
}
const merged = merge(options, defaults)
return fetch(url, merged)
}
}

Return in Http Response and Html page but its not showing on the browser in Django

I have created a page on locahost:8080/kar, i am sending an ajax POST request to different Url(same domain) i.e. locahost:8080/kar/create_post there i am returning an HTML response but its not showing on the browser as the URL is still on locahost:8080/kar, the data is stored in the database.Where as in the developer console i can see the response in the network tab .When i redirect it is also showing the same thing in the developer console
Why i am not able to change the URl and see the response ?
It's a client side thing, that means the desired behaviour needs to be implemented with javascript. Django is functioning normally here.
When you're sending Requests via AJAX, that is a non blocking request with the XMLHttpRequestheader set, your browser won't trigger the chain of events that occurs when a server side script evaluates your form and returns something, which may be data, or a redirect, depending on whether the form validated or not.
A typical AJAX call in jQuery looks like this:
$.ajax({
type: "POST",
url: url,
data: data,
success: success,
dataType: dataType
});
If you would like to perform some actions when the request you sent by XMLHttpRequest returns, you could attach that to the appropriate success handler:
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.post( "example.php", function() {
alert( "success" );
})
.done(function() {
alert( "second success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "finished" );
});
// Perform other work here ...
// Set another completion function for the request above
jqxhr.always(function() {
alert( "second finished" );
});
If you need to redirect to the URI that is returned as a redirect from your server you can get the redirect URI from the response in the success handler:
$.ajax({
type: "POST",
url: reqUrl,
data: reqBody,
dataType: "json",
success: function(data, textStatus) {
if (data.redirect) {
// data.redirect contains the string URL to redirect to
window.location.href = data.redirect;
}
else {
// data.form contains the HTML for the replacement form
$("#myform").replaceWith(data.form);
}
}
});
If you would like to modify the URL in the users bar without reloading the page you could have a look at this question.

Typeahead/Bloodhound - Using Jquery Ajax for remote causes only a single server side request

I need to use a jquery ajax setup in Bloodhound's remote property since I have a server side page that takes POST requests only. Everything works, but just once. Any subsequent change to the text in the typeahead input box calls the filter function, but does not fire a new server side request to fetch new data. It just filters through the data that it got in the first request. I need for it make a new request as the user removes the text and types in something else.
I am new to typeahead and I am spending way too much time trying to figure this out. Here is my code.
var users = new Bloodhound({
datumTokenizer: function (d) {
return Bloodhound.tokenizers.whitespace(d.value);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'fake.jsp',
filter: function (users) {
return $.map(users, function (user) {
return {
value: user.USER_ID,
name: user.DISPLAYNAME
};
});
},
ajax: {
type: 'POST',
data: {
param: function(){
return $('#userid').val();
}
},
context: this
}
}
});
users.initialize(true);
$('#userid').typeahead({
minLength: 3,
highlight: true
}, {
name: 'userslist',
displayKey: 'name',
source: users.ttAdapter()
});
I had the same solution and discovered jQuery's cache: false; option does not work in this situation for whatever reason. Here is the solution I found:
remote: {
url: ...
replace: function(url, query) {
return url + "#" + query; // used to prevent the data from being cached. New requests aren't made without this (cache: false setting in ajax settings doesn't work)
}
}
try this:
remote: {
url: 'fake.jsp/?' + Math.random(),
.
.
.
it's not really the solution but at least the results will be fetched from server everytime the page is refreshed.

Django 1.5 + django-ajax-upload-widget - jQuery $.ajax handle success response as error

I'm using django 1.5 + Mezzanine + django-ajax-upload-widget. I have the problem with the django-ajax-upload-widget.
So, when I trying to choose file in form I have an upload error. As I undestand (by using js debugger) - the problem is that jQuery use error handler to handle successful response.
So here is the view, which process ajax uploading:
#csrf_exempt
#require_POST
def upload(request):
form = UploadedFileForm(data=request.POST, files=request.FILES)
if form.is_valid():
uploaded_file = form.save()
data = {'path': uploaded_file.file.url,}
return HttpResponse(simplejson.dumps(data))
else:
return HttpResponseBadRequest(simplejson.dumps({'errors': form.errors}))
I also tried python debugger, so file uploading cause running of this line:
return HttpResponse(simplejson.dumps(data))
So, it means that file uploaded successfuly (I also checked destination folder - it contains this file). Using HttpResponse means that status of request is 200, as I understand. So, jQuery run error handler instead of success. So. it means that the problem may appear when jQuery try to process data, but here is js code:
$.ajax(this.$element.data('upload-url'), {
iframe: true,
files: this.$element,
processData: false,
type: 'POST',
dataType: 'json',
success: function(data) { self.uploadDone(data); },
error: function(data) { self.uploadFail(data); }
});
So, processData: false and here is no proccessing.
How do you think - what may cause the problem? And how to fix it?
ADDITION:
I changed error handler to
AjaxUploadWidget.prototype.uploadFail = function(jqXHR, textStatus, errorThrown){
if(this.options.onError) {
this.options.onError.call(this);
} else {
console.log('Upload failed:');
console.log(jqXHR, textStatus, errorThrown);
}
};
So, js console shows that it is "parsererror".
Problem SOLVED
I try to console.log(jqXHR.responseText); in error handler and see the following:
if (window.top.ripple) { window.top.ripple("bootstrap").inject(window, document); }{"path": "/static/media/ajax_uploads/c351360b8aa7417b89f51cdd9e9057ae-Koala.jpg"}
But I MUST see just this:
{"path": "/static/media/ajax_uploads/c351360b8aa7417b89f51cdd9e9057ae-Koala.jpg"}
So, I turn off Ripple plugin in my Chrome and all works fine o_O :-)
But it's very strange that some plugin can break the work of frontend js. Do you have any thoughts on this?