Updating info on html page using Ajax in Django - javascript

I have a problem with Ajax and how can I update info on my HTML page without reloading it.
So, I have a function in my views.py file:
def index(request):
some stuff
context = {
some stuff
}
return render(request, "header.html", context)
And I just use variables from {context} in my header.html file. And the question is - how can I perform index function and send new variables to my header.html file without reloading it?

First, create a new endpoint to get the desired data in whichever format. I prefer JSON.
New endpoint:
# views.py
from django.http import JsonResponse
def new_endpoint(request):
"""Returns `JsonResponse` object"""
# you can change the request method in the following condition.
# I dont know what you're dealing with.
if request.is_ajax() and request.method == 'GET':
# main logic here setting the value of resp_data
resp_data = {
'html': 'stuff',
# more data
}
return JsonResponse(resp_data, status=200)
Then, you need to code the AJAX part calling this endpoint with the method, data, headers, etc. and finally, define the success callback method to get the desired data.
AJAX:
var data = {};
$.ajax({
url: '/your-new-endpoint-url',
type: 'GET',
data: data,
dataType: 'json',
success: function(resp) {
$('#changingElement').html(resp.html);
}
});
You can send any type of data from this new endpoint to change whatever element's html text or class name or styles, etc.

Related

Updating page elements immediately on input changes with django and AJAX inside GET request

I want to update elements in the page to tell a user in real-time how many objects will be affected by their choice of criteria in a form.
For an example to work with, the form asks for a number and the django logic will delete any model instance with a pk less than that value once the submit button is clicked - but before clicking the user wants to know how many they will be deleting:
<span id="number-changed">NULL</span> objects will be deleted
so the end result I want is that #number-changed will be populated by a value like MyModel.objects.filter(pk__lt=input_number).count().
I have set up an AJAX call on changes to the input via:
$("input").change( function() {
$.ajax({
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
success: function (data) {
// code to update #number-changed
}
I am wondering how I implement in the view so that on successful GET the success function can use the value I retrieve. Some pseudo-code:
# views.py
class MyView(FormView):
# ...
def get(self, request, *args, **kwargs):
input_number = ???
number_changed = MyModel.objects.filter(pk__lt=input_number).count()
# presumably some super().get() call here
return ???
Questions:
Can I retrieve the current input_number via request or does it need to be passed as a url parameter when making the AJAX request?
How can I add my required information, number_changed in this case, to the return of the get() method, and how to access this inside success?
The way I have implemented AJAX with django before has being using POST requests and I simply return a JsonResponse with my required data. However, an initial get() is called when loading the page and needs to return a full HttpResponse - so ultimately is there a way to add my additional information into this, or am I going about it completely wrong.
An Ajax request is exactly the same as any other request from the point of view of the server. You can just include the data in the querystring, which you then access in the view via the request.GET dict.
jQuery will generate that querystring for you from the data parameter; note, you don't need a csrf token for a GET request. So:
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
input_number: $(this).val(),
},
...
And in the view:
def get(self, request, *args, **kwargs):
input_number = request.GET["input_number"]

AJAX not changing/redirecting from login page to dashboard [flask backend]

I am using the post method for the login. My ajax function sends the data successfully to my flask backend server [I know because it returns a response to my ajax]. Supposedly, after receiving the respnse from the backend, my ajax success handler will navigate/redirect to the dashboard page but IT DOES NOT! How do I make it navigate/redirect to another page/url?It returns a 200 status code so I do not know why it does not display the dashboard page.
WHAT I HAVE TRIED:
I have tried using window.location.href, window.location.replace but to no avail, still it does not work. I have also tried changing the method to GET but its still the same. I have also set async to false because ajax would not post if I would not set it to false.
AJAX
$.ajax({
type: "POST",
url: 'http://127.0.0.1:5000/processlogin',
data: JSON.stringify(loginobject),
contentType: "application/json;charset=utf-8",
async: false,
success: function (resp) {
window.location.href = ("http://127.0.0.1:5000/dashboard");
},//success
failure: function (resp) {
alert(resp.message);
}
});
backend flask functions
This functions work 100%. Already tested it with POSTMAN. I have also queried the database using my stored procedure and it does well.
This displays the login form
#app.route('/', methods=['GET','POST'])
def login():
return render_template('login.html')
This processes the ajax's sent data. In short this is the function ajax is communicating with
#app.route('/processlogin', methods=['POST'])
def processlogin():
loginobject = request.get_json(force=True)
username = loginobject['username']
password = loginobject['password']
try:
dbpassword = callstoredproc("getpassword", (username,))[0][0]
if dbpassword == 'null':
return jsonify({'status':'error', 'message':'Username does not exist!'})
elif bcrypt.verify(password, dbpassword) == True:
return jsonify({'status':'ok'})
except Exception as e:
print(e)
And this is what I am trying to display: the dashboard html
#app.route('/dashboard', methods=['GET', 'POST'])
def dashboard():
return render_template('dashboard.html')
Remove the curved brackets and try again:
window.location.href = "http://127.0.0.1:5000/dashboard";
It works also with curved brackets so just be sure that your response arrive correctly to the success callback.
See also best answer on SO.
It should also be error instead of failure as error callback.
error: function (resp) {
alert(resp.message);
}
jsfiddle Example

Passing a JSON string to django using JQuery and Ajax

I'm a bit new to Django and trying to understand it. Currently, I'm creating a network topology visualiser (think routers and switches connected together). It works fine and all of the data is saved in a javascript object.
I want to have the ability to, when a user clicks a button, send this javascript object to django so that it can be parsed and handled appropriately. I did a lot of research and found a bunch of similar implementation which use a combination of JQuery and ajax to POST a JSON string. This is some of my code currently:
mainapp/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^NetworkTopology/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^NetworkTopology/json/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^admin/', admin.site.urls),
]
NetworkTopology/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^json/$', views.returnjson, name='returnjson'),
]
NetworkTopology/views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
def index(request):
return render_to_response('index.html')
def returnjson(request):
if request.is_ajax():
request_data = request.POST
print("Raw Data: " + request_data.body)
return HttpResponse("OK")
JavaScript function (return JSON button is pressed):
function returnJsonTop(){
$(document).ready(function() {
$.ajax({
method: 'POST',
url: '/NetworkTopology/json',
dataType: 'json',
data: JSON.stringify(nodes.get(),null,4),
success: function (data) {
//this gets called when server returns an OK response
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
});
}
In my index template, I have created a button which calls the returnJsonTop() function when it is pressed:
<button id="submitJson" onclick="returnJsonTop();">Deploy</button>
Currently, when I press the Deploy button, I just get the 'it didn't work' alert that has been setup to handle an errors. I'd really appreciate someone pointing me in the right direction here. I suspect the issue is in my urls.py files but I've tried various combinations of urls without any luck.
You're trying to access body on request.POST. But body is an attribute directly of the request. Your code should be:
request_data = request.body
print("Raw Data: " + request_data)
Also note, in your Javascript that $(document).ready line makes no sense there; you should remove it.
For those reading this later, this is what I did:
mainapp/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^NetworkTopology/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^admin/', admin.site.urls),
]
NetworkTopology/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^json/$', views.returnjson, name='returnjson'),
]
NetworkTopology/views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.views.decorators.csrf import csrf_exempt
def index(request):
return render_to_response('index.html')
#csrf_exempt
def returnjson(request):
if request.is_ajax():
request_data = request.POST
print("Raw Data: " + str(request_data))
return HttpResponse("OK")
I was getting a 403 error so I added '#csrf_exempt'. I'll probably change this to handle it properly afterwards.
Return JSON function:
function returnJsonTop(){
$.ajax({
method: 'POST',
url: '/NetworkTopology/json/',
dataType: 'json',
data: JSON.stringify(nodes.get(),null,4)
});
}
First of all you dont even need to use all this in your ajax call
data: JSON.stringify(nodes.get(),null,4),
replace by
data: nodes.get(),
should be enough as long as this method returns a valid json object
Second one, I ´d strongly recommend you to use a framework to help you to parse JSON
Python have may, but to illustrate this example, I've used django rest framework, which is a very good one.
from django.shortcuts import render
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
import json
import controllers#this class belongs to my business logic layer, you can encapsulate yours and use instead of it
#in this solution you must create a pre-parser to handle responses
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
#csrf_exempt # this is for prevent invasions
def login(request):
#this one here handle your jquery post data into a valid json object in python represented by a Dict
envelopin = json.loads(request.body)
# here we pass the dict inside my business controll logic routine which also responds with a valid Python Dict
envelopout = controllers.login(envelopin)
# and for last, we use our pre-parser Class to make your response be handled by jquery as valid json
return JSONResponse(envelopout)
and that is it, you success jQuery data variable, will hold the envelopout json object, in the same shape as it has inside yor django-python code.
hope this help

Rails - Changing boolean in database from js.erb file

In my scenario in rails application after sharing content to facebook i will get a response object with post id
post_id: "mypostidhere"
If its not successful i will get response object with an error message.
So according to the response i want to change a boolean column of last row for the current user in my database table. And for this in my .js.erb file i tried to access current_user.model.last but it throws the following error.
undefined local variable or method `current_user' for
So how can i change the boolean column in database according to the response?
UPDATED
Ajax code
$.ajax({
type: "POST",
url: "/action"
});
Controller code
def action
current_user.modal.last.toggle!(:boolean-column-name)
end
It changes the table column successfully. But after that i am receiving an error in browser CONSOLE as below
POST http://URL/action
500 (Internal Server Error)
I am new to AJAX. What i am doing wrong in ajax request? Thanks in advance.
current_user is not a local variable to your JS function/file, it is a helper provided and available in your rails application.
So, what I will like to ask is:
How are you using current_user in the JS file?
What you can do is to make an ajax call to a controller method, and then access current_user directly from the controller.
If you want to change the db, you're going to have to communicate with your Rails app, which is done with ajax:
#app/assets/javascripts/application.js
... // your events will fire
$.ajax({
url: "/users/update",
method: "PUT",
data: { param: "value" }
success: function(data) {
// do something here
};
});
This will allow you to do the following:
#config/routes.rb
resources :users do
put :update, on: :collection
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def update
current_user.update(update_params)
end
private
def update_params
params.permit(:param)
end
end

JSON passed from Python (Flask) into JavaScript is displaying on screen

I am passing a JSON from a Python back-end into my front-end JavaScript where I'm running a webGL (three.js) animation. The JSON holds numerical values that determine what happens in the animation. My problem is that while I have a basic ajax request working, the JSON is being printed to the screen (in lieu of the animation) rather than becoming a variable I can iterate through to control aspects of the animation. The two halves of the call are shown below.
I asked a related question to this one before and got some great help, but am obviously still missing a piece of the puzzle. I've been reading docs and all sorts of sources, yet need a nudge in the right direction to finally get this working. Any help is appreciated!
In the python backend:
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/')
def index():
motifs = get_motif_list(10)
# The first version of the return below successfully sends data, yet it is printed to the
# screen, rather than being stored as data in a variable.
return Response(json.dumps(motifs), mimetype='application/json')
# This version of the return does not work:
# return render_template("index.html", motifs = motifs)
In the JavaScript (note that the console.log sanity checks don't work - I have no idea why:
function foo() {
var array_data;
$.ajax({
type: "GET",
url: "/",
dataType: "json"
});
request.done(function(JSON_array) {
array_data = JSON.parse(JSON_array)["array"]
console.log(array_data); // sanity check - doesn't work
});
return array_data;
};
var array = foo();
console.log(array); // sanity check - doesn't work
UPDATE
With help from the advice below, I'm pretty close to having this off the ground. The JSON is no longer printing to the screen (an issue caused by the Flask return), and I've solved a multifunction callback issue I discovered along the way. However, I am now getting a parsererror from the complete textStatus. I think the problem now lays in the Python/Flask (see current code below). Thanks again for all who've helped!
Python/Flask (I think the problem is here - I'm a noob to Flask):
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/')
def index():
motifs = get_motif_list(10)
return Response(json.dumps(motifs), mimetype='application/json')
#app.route("/")
def index():
return render_template("index.html")
The JavaScript (the data is returned by the Deferred object - used to solve a callback issue):
function getData() {
var deferredData = new jQuery.Deferred();
$.ajax({
type: "GET",
url: "/",
dataType: "json",
success: deferredData.resolve(),
complete : function(xhr, textStatus) {
console.log("AJAX REquest complete -> ", xhr, " -> ", textStatus)}
});
return deferredData; // contains the passed data
};
It turns out I had a lot of problems in my code above, several of which I had to debug in related questions here and here.
Among them were:
in my original Flask index() function, it was dumping the JSON data to the screen because I was not rendering the index.html template anywhere.
I had matching routes ('/') and function names (index()) in the Flask functions
As mentioned in the comments I did an unnecessary double parsing of the JSON with dataType: json and array_data = JSON.parse(JSON_array)
the return from this asynchonous function always came up undefined because it was referenced before the call had resolved
in my later update to a Deferred object, the success property should have read: success: function(data) { deferredData.resolve(data);}
So, after all those fixes, here is the functioning code!
Flask/Python:
from flask import Response, json, render_template, jsonify
from app import app
from motifs import get_motif, get_motif_list
#app.route('/ajax')
def ajax() :
motifs = get_motif_list(10)
return Response(json.dumps(motifs), mimetype='application/json')
#app.route("/")
def index():
return render_template("index.html")
JavaScript: (note: this is the foo() function in my question above)
function getData() {
var deferredData = new jQuery.Deferred();
$.ajax({
type: "GET",
url: "/ajax",
dataType: "json",
success: function(data) {
deferredData.resolve(data);
},
complete: function(xhr, textStatus) {
console.log("AJAX Request complete -> ", xhr, " -> ", textStatus);
}
});
return deferredData; // contains the passed data
};
// I used the Deferred structure below because I later added Deferred objects from other asynchronous functions to the `.when`
var dataDeferred = getData();
$.when( dataDeferred ).done( function( data ) {
console.log("The data is: " + data);
});
In your javascript:
function foo() {
var array_data;
$.ajax({
type: "GET",
url: "/",
dataType: "json"
});
request.done(function(JSON_array) {
/*JSON_array is already parsed and it is an object..*/
array_data = JSON.parse(JSON_array)["array"]
/* ^ I belive you dont have to do this ^*/
console.log(array_data);
/* ^ change this to console.log(JSON_array);*/
});
return array_data;
/* ^ change this to return JSON_array;*/
};

Categories

Resources