How to pass Django csrf token in AJAX (without jQuery) - javascript

Based on the w3schools ajax example I am trying to make a delete call and then remove the corresponding row from a table. There are plenty of answers here about how to do it using JQuery but I am not doing that. I found this answer which made me write my JavaScript like this:
function deleteFullLicense(rowid, objectid) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 204) {
row = document.getElementById(rowid);
row.parentNode.removeChild(row);
}
else {
window.alert("Something went wrong. The delete failed.");
}
};
xhttp.open("POST", "deleteLicense/" + objectid, true);
xhttp.send({'csrfmiddlewaretoken': '{{ csrf_token }}'});
}
But I get the Forbidden (CSRF token missing or incorrect.) message. How should I send the token?

Turns out if I called it X-CSRFToken instead it worked. Found out about it here if you want to read more.
function deleteFullLicense(rowid, objectid) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 204) {
row = document.getElementById(rowid);
row.parentNode.removeChild(row);
}
};
xhttp.open("POST", "deleteLicense/" + objectid, true);
xhttp.setRequestHeader("X-CSRFToken", '{{ csrf_token }}')
xhttp.send();
}

The header name X-CSRFToken actually comes from the parameter CSRF_HEADER_NAME in Django settings.py. When receiving frontend request (e.g. ajax call), Django internally checks header parameters and converts X-CSRFToken to HTTP_X_CSRFTOKEN which is default value of CSRF_HEADER_NAME .
The better approach would be to :
convert the value of CSRF_HEADER_NAME
render the converted value in previous step, to the HTML template
in the frontend code (e.g. the HTML template or separate js file), create a custom header with that value and the CSRF token on each ajax call for form submission.
Here's a quick example :
In settings.py
CSRF_HEADER_NAME = "HTTP_ANTI_CSRF_TOKEN"
In the view function of views.py
from django.conf import settings
from django.http.request import HttpHeaders
prefix = HttpHeaders.HTTP_PREFIX
converted = settings.CSRF_HEADER_NAME[len(prefix):]
converted = converted.replace('_','-')
# so the value HTTP_ANTI_CSRF_TOKEN is converted to ANTI-CSRF-TOKEN,
return Response(context={'custom_csrf_header_name':converted})
In your HTML template (not good practice, since this is just quick example)
<script>
// Note that the value is 'ANTI-CSRF-TOKEN'. when this header name goes to
// backend server, Django will internally convert it back to 'HTTP_ANTI_CSRF_TOKEN'
var custom_csrf_header_name = "{{ custom_csrf_header_name }}";
// the ajax part is almost the same as described in the accepted answer
...
xhttp.setRequestHeader(custom_csrf_header_name, '{{ csrf_token }}')
...
</script>

Related

Import a variable from Flask to a webpage without reloading it

I would like to import the variable test_data from Flask to my webpage, without reloading it. Just clicking a button. But I couldn't succeed so far. Any ideas?
Flask:
#blueprint.route('/data_analysis')
#login_required
def data_analysis():
test_data = 'getting data from here' ### THIS VARIABLE
return render_template('index.html', test_data= test_data)
Javascript:
$("#load_data_btn").click(function(){
var request = new XMLHttpRequest();
request.open('GET', '/home/data_analysis', true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var test_data = {{ test_data }};
alert(test_data);
// Success!
var resp = this.response;
} else {
// We reached our target server, but it returned an error
}};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
});
It looks like you're confusing Jinja which renders the html and javascript file before sending it to the client, and the server side stuff. What you're doing is creating an html file that will have something like:
<script>
. . .
var test_data = "getting data from here"; # hard coded when user visits site
alert(test_data); # rather than dynamically retrieved
. . .
</script>
But you're code probably isn't getting here because you're route isn't actually returning anything.
If you don't want to reload the page you should return the variable encoded as JSON rather than render the template:
from flask import jsonify
#blueprint.route('/data_analysis')
#login_required
def data_analysis():
return jsonify({"value": "getting data from here"})
$("#load_data_btn").click(function(){
$.getJSON("/home/data_analysis", function(response){
alert(response["value"]);
});
});

Ajax with CakePHP and Javascript

i' m pretty new in using CakePHP and Javascript, i read many articles about request handling in cake, but i'm still confused, what i'm try to do is to send ajax request from my Javascript code to cakePHP and obtain some data in json format, i tried many ways to do this, but all the time I get simply html of page, instead of data i want to get, I have generated by default app controller class, as a url in Javascript request i use "http://localhost/pages/main" which is url of my view page where i have input controls, i wonder where in controller class should i put code responsible for handling request, and how to implement sending json response, thanks in advance
php code AppController class
public function beforeRender(Event $event)
{
// Note: These defaults are just to get started quickly with development
// and should not be used in production. You should instead set "_serialize"
// in each action as required.
if (!array_key_exists('_serialize', $this->viewVars) &&
in_array($this->response->type(), ['application/json', 'application/xml'])
) {
$this->set('_serialize', true);
if ($this->request->is('ajax')) {
$data = ['data1', 'data2'];
$this->set(compact('data'));
$this->set('_serialize', ['data']);
}
}
**javascript:**
var xhr = new XMLHttpRequest();
var url = 'localhost/pages/main.json';
var data = {
unit: 'someUnit',
name: this.name
};
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log(xhr.response);
}
};
xhr.open('POST', url);
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(data);
It is easier if you use routing extension
Router::extensions(['json']);
then in your controller you can pass the serialize data like this
$data = $this->Model->find();
$this->set(compact('data');
$this->set('_serialize', ['data']);
In your ajax request, just add .json extension to the url
You can start here: CakePHP official documentation for REST
Example:
// src/Controller/RecipesController.php
class RecipesController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
}
public function index()
{
$recipes = $this->Recipes->find('all');
$this->set([
'recipes' => $recipes,
'_serialize' => ['recipes']
]);
}
}

Calling JavaScript function after updating table with PHP

I have a simple website that uses JavaScript to collect user input and sends data to PHP script (script is an external php file) via AJAX request. PHP script updates database with this information.
Now, i have a JS function on my website that i want to call only after PHP script is sucessfuly run and database updated. I don't need any data from database or PHP script, i only want to make sure that database is updated before calling this Javascript function.
This is what AJAX request looks like:
function ajax_post(){
if (typeof featureId !== 'undefined') {
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// Create some variables we need to send to our PHP file
var url = "parse_file.php";
var fn = featureId;
var vars = "featureId="+fn;
hr.open("POST", url, true);
// Set content type header information for sending url encoded variables in the request
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Access the onreadystatechange event for the XMLHttpRequest object
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var return_data = hr.responseText;
document.getElementById("status").innerHTML = return_data;
}
}
// Send the data to PHP now... and wait for response to update the status div
hr.send(vars); // Actually execute the request
document.getElementById("status").innerHTML = "processing...";
hilites.destroyFeatures();
featureId = undefined;
}
else {
window.alert("Select polygon first");
}
}
What is the best way to do this? Some examples would really help.
Looking at your code, you simply need to call the function around this part:
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var return_data = hr.responseText;
document.getElementById("status").innerHTML = return_data;
// CALL YOUR FUNCTION HERE
}
}
The best solution is to use a Promise. However, this is not supported in IE 11, so you will need to use a polyfill on some browsers.
Here is an example using jQuery.
// This is the function you want to call after the script succeeds
function callbackSuccess() {
console.log('Done!');
}
// This is the data you want to submit to the PHP script
var myData = {
hello: "world"
};
// This is the actual AJAX request
$.post('/my-script.php', myData).done(function(){
callbackSuccess();
});
Add this to the end of your php save-function:
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array('status' => 'SUCCESS'));
Making the call:
$.getJSON('url_to_your_php_file.php', function(data) {
if (data.status == 'SUCCESS') {
console.log('Save complete');
}
else {
console.log('oops, something went wrong!!');
}
});
It's possible to return something like ERROR, this will return:
console.log('oops, something went wrong!!');
You may try the following:
In php you can use return code from sql statement
echo $sqlResult = $conn->query($sqlStatement);
On Javascript, you can try the following
$.ajax({
url: 'file.php',
type: 'POST',
data: {
data1 : data1,
data2: data2
},
success: function(data){
if(data == success_code){
alert("Success")
}
}
Hope this helps!
Completing ajax request without errors does not mean that the data is saved to DB without errors.
Even if your PHP script fails to save the data, it probably echos some error message or even empty output as regular HTTP response, and it would show as success as far as the ajax request goes.
If your intention is to make sure that the data is really saved before calling the JS function, then the PHP script should containg enough error handling.
If you write the PHP script to return response status code based on the real outcome of save operation, then you can rely on those status codes in ajax response handling (success = ok, error = not ok).
Bu what I usually do, is that instead of using HTTP status codes, I echo "OK" or something similar at the end of succesfull PHP execution (and "ERROR" if there are any errors), and then check for those strings in ajax response handler (hr.responseText in your code).
Maby you have to try this:
setTimeout(function(){
//your function here...
}, 500);

Retrieve HTML of ReadMe

Hi so first time working with APIs like this. Anyways, I've been reading up on the GitHub API and came across this:
READMEs support custom media types for retrieving the raw content or rendered HTML.
src: https://developer.github.com/v3/repos/contents/#get-the-readme
Which I believe means that it is possible to retrieve an HTML formatted version of the contents of the README? If so how would I retrieve it using AJAX since the tutorials are all for curl. In the end I want to display a portion of it on my website and would be a lot easier if given in the html format rather then markdown.
The docs say something about: application/vnd.github.VERSION.html
I just don't necessarily know how to use it.
Thanks!
You have to set the Accept header of the HTTP request to application/vnd.github.html.
$.ajax({
url: 'https://api.github.com/repos/just95/toml.dart/readme',
headers: { 'Accept': 'application/vnd.github.html' }
}).done(function(data) {
alert(data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
All you need to do is set the Accept header of your HTTPS request. Using cURL for example:
curl -i -H "Accept: application/vnd.github.v3.html" https://api.github.com/repos/github/developer.github.com/readme
In JavaScript,
var apiRoot = 'https://api.github.com';
var myUser = YOUR_USER_HERE;
var myRepo = YOUR_REPO_HERE;
var request = new XMLHttpRequest();
request.open('GET', apiRoot + '/repos/' + myUser + '/' + myRepo + '/readme');
request.setRequestHeader('Accept','application/vnd.github.v3.html');
/* add event listeners... */
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
document.body.innerHTML = request.response;
}
};
request.send();

I can't send PHP variables to JavaScript

I'm trying to send parametres from a .php file to my Javascript but I can't even manage to send a String.
Javascript fragment:
var params = "action=getAlbums";
var request = new XMLHttpRequest();
request.open("POST", PHP CODE URL, true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.setRequestHeader("Content-length", params.length);
request.setRequestHeader("Connection", "close");
request.send(params);
request.onreadystatechange = function() {
var phpmessage = request.responseText;
alert(phpmessage);
};
PHP fragment:
$deviceFunction = $_POST["action"];
if ($deviceFunction == "") $deviceFunction = $_GET["action"];
// Go to a function depending the action required
switch ($deviceFunction)
{
case "getAlbums":
getAlbumsFromDB();
break;
}
function getAlbumsFromDB()
{
echo "test message!";
}
The alert containing phpmessage pops up but it's empty (it actually appears twice). If I do this the alert won't even work:
request.onreadystatechange = function() {
if(request.status == 200) {
var phpmessage = request.responseText;
alert(phpmessage);
}
};
The readystatenchange event will be called each time the state changes. There are 5 states, see here: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#readyState
Rewrite your JS:
request.onreadystatechange = function () {
if (request.readyState == 4) {
console.log('AJAX finished, got ' + request.status + ' status code');
console.log('Response text is: ' + request.responseText);
}
}
In your code, you only check for the returned status code. The code above will check for the ready state and then output the status code for debbuging.
I know that this answer is more a comment than an answer to the actual question, but I felt writing an answer in order to include nicely formatted code.
I faced a similar problem working with Django. What I did:
I used a template language to generate the javascript variables I needed.
I'm not a PHP programmer but I'm going to give you the idea, let me now if works. The following isn't php code, is just for ilustrate.
<?php
<script type="text/javascript" ... >
SOME_VARIABLE = "{0}".format(php_function()) // php_function resolve the value you need
</script>
?>
The I use SOME_VARIABLE in my scripts.
Please specify your onreadystatechange event handler before calling open and send methods.
You also should make your choice between GET and POST method for your request.
If you want to popup your message only when your request object status is OK (=200) and readyState is finished whith the response ready (=4), you can write :
request.onreadystatechange = function() {
if (request.readyState==4 && request.status==200) {
var phpMessage = request.responseText;
alert(phpMessage);
}
};

Categories

Resources