Convert JQuery Ajax code to plain JavaScript - python

This is Ajax code in my application, it adds object in Model without refreshing the page and shows no error:
$(document).on('submit', '#addbookform', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: "{% url 'books:home' %}",
data: {
name: $('#name').val(),
price: $('#price').val(),
num_of_pages: $('#num_of_pages').val(),
csrfmiddlewaretoken: "{{ csrf_token }}"
},
success: function () {
alert('Form submitted successfully!!');
}
})
})
I tried to convert it to JavaScript, however it add objects to model, but it refreshes the page and moreover it shows a 403 error in console and then fade away.
document.querySelector('#addbookform').onsubmit = savebook;
function savebook() {
const name = document.querySelector('#name').value;
const price = document.querySelector('#price').value;
const num_of_pages = document.querySelector('#num_of_pages').value;
const url = "{% url 'books:home' %}"
const xhr = new XMLHttpRequest();
xhr.onload = function () {
if (this.status == 200) {
alert("Saved!");
}
}
xhr.open('POST', url, true);
xhr.send();
}
Can you please help me solve it?

Related

Returning two arrays from a python script in Django and utilizing in Ajax simultaneously

I have a python script running in views.py within Django which returns two very large string arrays, x and y. It currently is able to run off a button press within my index.html.
def python_file(request):
final()
return HttpResponse("ran")
The ajax code I have running to do the button press.
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>
function gotoPython(){
$.ajax({
url: "/python_file",
context: document.body
}).done(function() {
alert('finished python script');
});
}
</script>
It's also attached to the URLS.py. I know there's no array being returned right now, because I am unsure how to run the script, get the data simultaneously, then add it to the page without refreshing the page. So, I am asking what would be the best practice to do what I described. Any help would be appreciated.
This is generally what I do, not sure if it's best practice, but I return it with Json
I included two examples, and POST and a GET.
I also included some other stuff I usually return status and msg. When I catch an error or have an invalid POST I send back status = False and msg = '{error message}, then I can show that error message in the front end with Javascript. I keep this standardized in my project, but you do you.
def python_file(request):
xArray, yArray = final()
import json
data = {
'status': True, # True=All Good. False=Caught Error but didn't crash.
'x': xArray,
'y': yArray,
'msg': 'returning x and y arrays',
}
return HttpResponse(
json.dumps(data),
content_type="application/json"
)
function gotoPython(){
$.ajax({
method: 'GET',
url: '/python_file',
success: function(data){
console.log(data)
if (data['status']){
// do things with arrays
data['x']
data['y']
}else{
console.log('Server Replied with Error, but did not Crash');
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
// general `xhr.status` Key for common errors
// 0 = Server didn't Reply (Server Down)
// 400 = Bad Request (Syntax Error)
// 403 = Forbidden (Login Token Expired or not in Group)
// 403 = Not Found (Invalid Url)
// 500 = Server Error (Django Crash)
},
});
};
function gotoPythonWithData(){
// if you wanted to POST data to this function you'd just do
// Note: Requires csrfmiddlewaretoken in template
// Throw this anywhere (it's hidden): {% csrf_token %}
submitData = {
'return_item_count': 25,
'csrfmiddlewaretoken': $('[name=\'csrfmiddlewaretoken\']').val(),
};
$.ajax({
method: 'POST',
url: '/python_file',
data: submitData,
success: function(data){
if (data['status']{
// do stuff
}else{
console.log(data['msg']);
};
},
error: function(event,xhr,settings,errorText){
},
});
};
Note: Some things like, Django Decimal objects, can not be be put into a Json Dump. In the Decimal example you've got to turn them into a Float or an Int
You can add parameters to the ajax.done(function) in order to get what your server returned.
$.ajax({
url: "/python_file",
context: document.body
}).done(function (response, textStatus, jqXHR) {
// What happens when the call is successful (200 <= status code < 300
console.log(response); // Logs what you returned from your django
// x + "separator" + y
})
.fail(function (jqXHR, textStatus, errorThrown) {
// Status code over 400
})
.always(function (jqXHR, textStatus, errorThrown) {
// Always happens
...
});
You can check ajax documentation here : https://api.jquery.com/jquery.ajax/#jQuery-ajax-settings-settings
And your django view should return some text content :
def view(response):
// code
return HttpResponse(status=200, content=x + "separator" + y)

Make AJAX continue working and update its status on UI even if user redirects or navigates to another page

I'm using Flask and JQuery to try to achieve this but pls feel free to suggest any other stack(React/Angular) if that's super easy.
I have the below AJAX in a poll.js file
$(document).ready(function(){
$('#poll').click(function(){
$('#poll').text("Working...")
$.ajax({
url: '/poll',
data: $('form').serialize(),
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
error: function(error){
console.log(error);
$('#poll').text("Poll")
}
});
});
});
and my poll function in app.py is as below:
#app.route('/poll', methods=['GET'])
def poll():
call an api and return the json response
now on the UI if i click the poll button its text changes to working and it calls the function which eventually hits the API.
While this is happening, if click the home menu or navigate elsewhere on the page, i loose the AJAX call.
How do i make the ajax call continue working i.e. calling the api and updating the UI even if we try to redirect to another page or click anywhere else?
I suggest to load the data on initial page load and then refresh after set interval. to achieve this following should give you a kick start
<script type="application/javascript">
jQuery(document).ready(function($){
/* change this
$('#poll').click(function(){
$('#poll').text("Working...")
$.ajax({
url: '/poll',
data: $('form').serialize(),
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
error: function(error){
console.log(error);
$('#poll').text("Poll")
}
});
});
*/
//to this it will start with page load and refresh $('#poll') every 5 seconds
var setInt = setInterval($(function(){
$('#poll').text("Working...")
$.ajax({
url:'path to script',
data: $('#form').serialize(), //your html must have form with id="form" for this
type: 'GET',
success: function(response){
console.log(response);
$('#poll').text("Poll")
},
}).fail(function(xhr,ajaxOptin,thrownError){
//console.error(xhr.responseText);
console.error(thrownError);
});
}), 5000);
});
</script>

ajax GET type not passing data to flask

I have a method that tries to pass a variable to flask with the GET method. This is the code from jquery and flask:
const impacttoolbtn = document.querySelector(".changingtoolbtn")
impacttoolbtn.addEventListener("click", function (){
$.ajax({
url: "{{ url_for('impact') }}",
contentType: "application/json",
data: JSON.stringify(login_bool),
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(err) {
console.log(err);
}
});
})
where login_bool is true or false.
and flask:
#application.route('/impact', methods=["GET"])
def impact():
data = request.get_json()
print(data)
print("hi")
return render_template('/impacttool.html')
and I get "None" on print(data), while if I do POST on ajax instead of the default GET I get the right data I need. Any reason why this may happen? I would love some insights, thank you so much.
You have not defined the method type in ajax call.
$.ajax({
type:"GET",
url: "{{ url_for('impact') }}",
contentType: "application/json",
data: JSON.stringify(login_bool),
dataType: "json",
success: function(response) {
console.log(response);
},
error: function(err) {
console.log(err);
}
});

Cannot retrieve data from endpoint

I have installed Chatterbot for Django integration. I followed the easy tutorial with every step and made it so that the endpoint was: http://127.0.0.1:8000/chatterbot/ What I did next was try to communicate with that endpoint to see if I would get back any results. So I made an Ajax request as follows:
var query = {"text": "My input statement"};
$.ajax({
type: 'POST',
url: "http://127.0.0.1:8000/chatterbot/",
data: JSON.stringify(query),
contentType: 'application/json',
success: function (data) {
console.log(data);
}
});
However, what returns in console is: POST http://127.0.0.1:8000/chatterbot/ 403 (Forbidden) and what returns in the cmd prompt when I run my server is:
csrf: WARNING - Forbidden (CSRF token missing or incorrect.):
/chatterbot/ [29/Mar/2018 02:16:43] "POST /chatterbot/ HTTP/1.1" 403
2502
Why am I getting this error? How can I fix it so I receive the call back from the endpoint?
View for this page:
def IndexView(request):
latest_questions = Questions.objects.all().order_by("-date_published")[:5]
popular_questions = Questions.objects.all().order_by("-num_replies")[:5]
return render(request, 'core/index.html',
{'latest_questions': latest_questions, 'popular_questions': popular_questions
})
Try this code
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
var query = {
"text": "My input statement",
"csrfmiddlewaretoken": csrftoken
};
$.ajax({
type: 'POST',
url: "http://127.0.0.1:8000/chatterbot/",
data: query,
contentType: 'application/json',
success: function (data) {
console.log(data);
}
});
one way is to send the csrfmiddlewaretoken like below
var query = {
"text": "My input statement",
'csrfmiddlewaretoken': "{{csrf_token }}"
};
other way is to use #csrf_exempt decorator
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def IndexView(request):
# .... code.....
other is to add a script
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Reference: https://docs.djangoproject.com/en/2.0/ref/csrf/
If you dont want to use CSRF tokens just add this above your code.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def IndexView(request):
# your code

How to lock function from multiple ajax requests in short period of time without threads

I'm dealing with the problem I've seen some people also struggling. I need some functionality based on Facebook like buttons events. So I catch the event of clicking button and on it call my function with ajax. But on each single click my function is called multiple times, varying from 3 to 8. Problem is that this function creates models that ought to be unique, and because of the instant multiple call - I get multiple objects.
How to prevent this ? I've tried setting global var, but without any luck :
def send_submission(request):
global BLOCKED
if BLOCKED == 0:
logging.debug("should be locked")
BLOCKED = 1
(... do something...)
BLOCKED = 0
html = render_page(request)
ajax = simplejson.dumps({
"html": html
}, cls=LazyEncoder)
return HttpResponse(ajax, mimetype='application/javascript')
And the js grabbing the call:
FB.Event.subscribe('edge.create', function(href, widget) {
$.ajax({
type: "POST",
url: "/submissions/add",
data: "href="+href+"&ip={{ IP_ADDRESS }}",
dataType: 'json',
success: function(data){
$("#submissions").html(data["html"])
}
});
return false;
});
I've tried locking it with js, but it does not work either.
<script type="text/javascript">
window.fbAsyncInit = function() {
var maxAjaxCallAllowed=1;
var openAjaxCalls = new Array();
function insertHtml(data){
openAjaxCalls.pop();
$(".list-submissions").html(data["html"])
}
FB.init({appId: '161771113844567', status: true, cookie: true, xfbml: true});
FB.Event.subscribe('edge.create', function(href, widget) {
alert("glos");
if(openAjaxCalls.length < maxAjaxCallAllowed){
openAjaxCalls.push(1);
$.ajax({
type: "POST",
url: "{% url register_vote %}",
data: "href="+href+"&ip={{ IP_ADDRESS }}",
dataType: 'json',
success: function(data){
insertHtml(data);
}
});
}
else{
alert('Server call not possible at this time');
}
});
};
(function() {
var e = document.createElement('script');
e.type = 'text/javascript';
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
</script>
If I am getting your issue correct, I think you should define a global variable in javascript. Say you have a global variable busy which should be set once a request is sent and unset when the request is completed.
Before every request you should check whether the variable is set and if its set do not send the request again.

Categories

Resources