Ajax JSON response not working - javascript

I am trying to fetch JSON response from my Django App but response is not working :
Here is my views.py :
import json
import traceback
from django.http import HttpResponse
from django.template import Context,loader
from django.template import RequestContext
from django.shortcuts import render_to_response
from eScraperInterfaceApp.eScraperUtils import eScraperUtils
#------------------------------------------------------------------------------
def renderError(message):
"""
This function displays error message
"""
t = loader.get_template("error.html")
c = Context({ 'Message':message})
return HttpResponse(t.render(c))
def index(request,template = 'index.html',
page_template = 'index_page.html' ):
"""
This function handles request for index page
"""
try:
context = {}
contextList = []
utilsOBJ = eScraperUtils()
q = {"size" : 300000,
"query" :{ "match_all" : { "boost" : 1.2 }}}
results = utilsOBJ.search(q)
for i in results['hits']['hits']:
contextDict = i['_source']
contextDict['image_paths'] = json.loads(contextDict['image_paths'])
contextList.append(contextDict)
context.update({'contextList':contextList,'page_template': page_template})
if request.is_ajax(): # override the template and use the 'page' style instead.
template = page_template
return render_to_response(
template, context, context_instance=RequestContext(request) )
except :
return renderError('%s' % (traceback.format_exc()))
def search (request,template = 'index.html',
page_template = 'index_page.html' ):
try:
if request.method == 'POST':
context = {}
contextList = []
keyWord = request.POST['keyWord']
print keyWord
utilsOBJ = eScraperUtils()
results = utilsOBJ.search('productCategory:%(keyWord)s or productSubCategory:%(keyWord)s or productDesc:%(keyWord)s' % {'keyWord' : keyWord})
for i in results['hits']['hits']:
contextDict = i['_source']
contextDict['image_paths'] = json.loads(contextDict['image_paths'])
contextList.append(contextDict)
context.update({'contextList':contextList,'page_template': page_template})
if request.is_ajax(): # override the template and use the 'page' style instead.
template = page_template
return HttpResponse(template, json.dumps(context), context_instance=RequestContext(request),
content_type="application/json")
except :
return renderError('%s' % (traceback.format_exc()))
#------------------------------------------------------------------------------
index.html :
<html>
<head>
<title>Fashion</title>
<link rel="stylesheet" type="text/css" href="static/css/style.css">
</head>
<body>
<form action="">
{% csrf_token %}
<input id="query" type="text" />
<input id="search-submit" type="button" value="Search" />
</form>
<div class="product_container">
<ul class="product_list">
<div class="endless_page_template">
{% include page_template %}
</div>
</ul>
</div>
<div class="product_container">
<ul class="product_list">
<div class="endless_page_template">
{% include page_template %}
</div>
</ul>
</div>
{% block js %}
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="static/js/endless_on_scroll.js"></script>
<script src="static/js/endless-pagination.js"></script>
<script>
$.endlessPaginate({paginateOnScroll: true,
endless_on_scroll_margin : 10,
paginateOnScrollChunkSize: 5
});</script>
<script type="text/javascript">
$("#search-submit").click(function() {
// Get the query string from the text field
var query = $("#query").val();
alert(query);
data = { 'csrfmiddlewaretoken': '{{ csrf_token }}', 'keyWord' : query};
// Retrieve a page from the server and insert its contents
// into the selected document.
$.ajax({
type: "POST",
url: '/search/',
data: data,
success: function(context,status){
alert("Data: " + context + "Status: " + status);
},
error: function( error ){
alert( error );
},
contentType: "application/json; charset=utf-8",
dataType: 'json',
});
});
</script>
{% endblock %}
</body>
</html>
index_page.html :
{% load endless %}
{% paginate 10 contextList %}
{% for item in contextList %}
<li >
<a href="{{ item.productURL }}" ><img src="/images/{{ item.image_paths.0 }}/" height="100" width="100" border='1px solid'/></a>
<br>
<span class="price">
<span class="mrp">MRP : {{ item.productMRP}}</span>
{% if item.productPrice %}<br>
<span class="discounted_price">Offer Price : {{ item.productPrice}}</span>
{%endif%}
</span>
</li>
{% endfor %}
{% show_more "even more" "working" %}
What i want is to fetch the server response and update the contextList .... But it is not working....

The problem you're facing is that you're trying to update a Django template compiled variable called context_list this won't happen magically by using AJAX since Django has precompiled the HTML you're serving when you hit the page initially.
You can't circumvent this but you can work around it and below I'll show you two ways of doing it.
Your success() handler in your jQuery script that you have that manages the search gets the newly HTML that you've recompiled but you're not using it anywhere ergo, it won't work.
In this case you're just logging some stuff out to console. (This would be where you're using option #2.)
You have two options as I see it. (It's a lot of code so I'll give you the pointers and not the implementation, won't strip you of all the fun!)
I'll give you a quick run down of both and then you can decide which way you want to take.
You can use jQuerys $.load() method in order to fetch a
recompiled template.
You can use $.getJSON() and get the
objects in JSON format and then update the HTML accordingly.
First option - $.load()
#Django
def search_view(keyword, request):
search_result = SearchModel.objects.filter(some_field=keyword)
t = loader.get_template("some_result_template.html")
c = Context({'search_results':search_result})
return render(t.render(c))
#jQuery
$("#result").load("url_to_your_search", { 'keyword': 'search_me' } );
Second option - $.getJSON()
#Django
from django.core import serializers
def search_view(keyword, request):
search_result = SearchModel.objects.filter(some_field=keyword)
json_data = serializers.serialize('json', search_result)
return HttpResponse(json_data, mimetype='application/json')
#jQuery
$.getJSON('url_to_your_search_view', { keyword: "search_me" }, function(json_data) {
var items = [];
$.each(json_data, function(key, val) {
items.push('<li id="' + key + '">' + val + '</li>');
});
$('<ul/>', {
'class': 'my-new-list',
html: items.join('')
}).appendTo('body');
});
Now the JSON code is taken straight from the docs, so you would have to modify it but you get the gist of what's needed in order for yours to work.

Related

how to pass js value to flask route

This is my list where i tried to get the value of the of a tag
{% extends 'base.html'%}
{% block body %}
<div onclick="pass()">
{{list1[1]}}
</div>
here i tried to get the value of a tag and have tried to pass info route
<script>
function pass() {
var a = document.getElementsByTagName('a');
var w = console.log(a[0].outerHTML);
window.location = "/info/" + w;
}
</script>
{% endblock %}
but show the following error
Not Found
http://127.0.0.1:5000/info/undefined
this is my info route
#app.route('/info', methods=['GET', 'POST'])
def info():
result = request.get_data
print(result)
return render_template('info.html', result=result)
why it's not displaying any data of within a tag
Thank you in Advance
window.location simply opens an HTML page. window.location = "/info/" + w; creates a route /info/w/ but you've only specified the route /info.
You need to send the a data to the server via a form and use Flask's request object to access it.

How to Embed multiple tweets of various users into HTML in django framework?

I am passing a data in the form of a dictionary from views.py to results.html in Django framework. The dictionary has the following format
'tweet': (tweet_analysis, tweet_id)
now in results.html, called by the views.py,
I am trying to Embed all the tweets that are passed to results.html, but the following code only displays one embedded tweet.
dicPositive: This is the dictionary containing all the tweets data
{% for tweet, tweet_feel in dicPositive.items %}
<div id="tweet" tweetID="{{tweet_feel.1}}"></div>
<script sync src="https://platform.twitter.com/widgets.js"></script>
<script>
window.onload = (function(){
var tweet = document.getElementById("tweet");
var id = tweet.getAttribute("tweetID");
twttr.widgets.createTweet(
id, tweet,
{
conversation : 'none', // or all
cards : 'hidden', // or visible
linkColor : '#cc0000', // default is blue
theme : 'light' // or dark
})
.then (function (el) {
el.contentDocument.querySelector(".footer").style.display = "none";
});
});
</script>
<!-- <li>{{tweet}} –> {{tweet_feel.0}} –> {{tweet_feel.1}}</li> -->
{% endfor %}
It is because you have used same id for multiple HTMLElements created while looping.
You must add loop counter to id attribute of div and also when
you are fetching it using getElementById inside script tag
{% for tweet, tweet_feel in dicPositive.items %}
<div id="tweet_{{forloop.counter}}" tweetID="{{tweet_feel.1}}"></div>
<script sync src="https://platform.twitter.com/widgets.js"></script>
<script>
window.onload = (function(){
var tweet = document.getElementById("tweet_{{forloop.counter}}");
# Rest of your code
...
</script>
{% endfor %}

Make an AJAX request to Flask application

I'm trying to refresh a Jenkins build console output in my Flask web application, however I am having trouble with the jQuery/AJAX to do it.
As you can see below, i'm just trying to get this working using a refresh button. Ideally I want to refresh {{buildinfo}} on a timer.
Currently my test function/jQuery is returning the error: Uncaught TypeError: Illegal invocation.
Heres the (working) function from my app.py I was using before I started down this path:
#app.route('/buildinfo/<job_id>/<job_number>', methods=['GET', 'POST'])
def buildInfo(job_id, job_number):
try:
console_output = server.get_build_console_output(job_id, int(job_number))
return render_template("buildinfo.html", buildinfo=console_output, job_id=job_id, job_number=job_number)
except Exception as e:
return render_template("buildinfo.html", error=str(e))
Here's the test function I have been using to receive the request and send back to the client:
#app.route('/_test')
def foo():
a = request.args.get('a', None, type=str)
b = request.args.get('b', 0, type=int)
bar = server.get_build_console_output(a, int(b))
return jsonify(result=bar)
And here is the buildinfo.html:
{% extends "base.html" %}
{% block content %}
<script type="text/javascript" src="{{ url_for('static', filename='jquery-1.12.0.min.js') }}"></script>
<script type="text/javascript">
var $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
$(function() {
$('a#load').bind('click', function() {
$.getJSON($SCRIPT_ROOT + '/_test', {
a: $('{{job_id}}'),
b: $('{{job_number}}')
}, function(data) {
$("#result").text(data.result);
});
return false;
});
});
</script>
<div class="col-md-10">
<h1>Build Info</h1>
<br>
<p>retrieving {{job_id}}, build number {{job_number}}</p>
<br>
<p>{{buildinfo}}</p>
<br>
<span id="result">?</span>
go
</div>
{% endblock %}
You're feeding a HTML elements to the ajax call, when you should be passing values. Change this:
a: $('{{job_id}}'),
b: $('{{job_number}}')
to this:
a: {{job_id}},
b: {{job_number}},
...
I'm not sure about the types you're sending, if you need to send strings- wrap quotes around the double-moustache, but this should get you going. See here for a similar issue.
For anyone in the same boat, I am able to refresh a Flask value using the following. I may update this answer to include clearInterval() once the build is complete. Thanks to GG_Python for pointing out my mistake.
app.py :
#app.route('/buildinfo/<job_id>/<job_number>', methods=['GET', 'POST'])
def buildInfo(job_id, job_number):
try:
console_output = server.get_build_console_output(job_id, int(job_number))
return render_template("buildinfo.html", buildinfo=console_output, job_id=job_id, job_number=job_number)
except Exception as e:
return render_template("buildinfo.html", error=str(e))
#app.route('/_test')
def foo():
a = request.args.get('a', None, type=str)
b = request.args.get('b', 0, type=int)
bar = server.get_build_console_output(a, int(b))
return jsonify(result=bar)
buildinfo.html :
{% extends "base.html" %}
{% block content %}
<script type="text/javascript" src="{{ url_for('static', filename='jquery-1.12.0.min.js') }}"></script>
<script type="text/javascript">
var $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>
<script type="text/javascript">
setInterval(function() {
$.getJSON($SCRIPT_ROOT + '/_test', {
a: "{{job_id}}",
b: {{job_number}}
}, function(data) {
$("#result").text(data.result);
});
return false;
}, 3000);
</script>
<div class="col-md-10">
<h1>Build Info</h1>
<br>
<p>retrieving {{job_id}}, build number {{job_number}}</p>
<br>
<p id="result">{{buildinfo}}</p>
<br>
</div>
{% endblock %}

Adding a context variable with AJAX in Flask

I have a select form that needs to be populated through AJAX. Consider this simple example:
templates/index.html
<!DOCTYPE html>
<html>
<body>
<select id="elements">
</select>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script>
$.ajax({
url: '/get-something/5',
type: "GET",
dataType: "html",
success: function (msg) {
$('#elements').html(msg)
}
})
</script>
</body>
</html>
app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/get-something/<int:n>')
def get_something(n):
result = ''
for i in xrange(n):
result += "<option value='%s'>%s</option>\n" % (i, i)
return result
if __name__ == '__main__':
app.run(debug=True)
That works just fine and is what I did. But, I was wondering if there exists another (better?) way.
For instance, I'd prefer having a context variable to better separate the view from the controller. Something like this:
app.modified.py
#app.route('/get-something/<int:n>')
def get_something(n):
return dict(elements=xrange(n))
templates/index.modified.html
<select id="elements">
{% for elem in elements %}
<option value='{{ elem }}'>{{ elem }}</option>\n
{% endfor %}
</select>
Unfortunately, that does not work. It says, 'dict' object is not callable.
Any help please? Is this even possible? Notice that I don't want to reload the page, I want the same behavior that you get in the AJAX example.
Using index.modified, you need to do something like this:
return render_template('index.modified.html',
elements=your_dictionary)
Not trying to return a dictionary (which is why you are getting that error). See http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ii-templates fore more examples
You should be returning render_template('index.modified.html', elements=xrange(n)) since you want the html.
render_template returns a string which you can then encode as JSON. Ex:
data = render_template('index.modified.html', elements=xrange(n))
return json.dumps({'data': data})

Symfony2: AJAX request returns full page html

I'm trying to get a simple AJAX request to work in Symfony2. It seems that the request is never reaching the controller. Instead of alerting the number '123', the AJAX request returns the HTML of the current page (index.html.twig). I have a feeling that since the pattern of the AJAX route is pointing to the current page I am on, the AJAX response is being filled with the output of the current page rather than getting the response from the Controller. Is there any way that I can get just the value from the Controller? Any help would be greatly appreciated.
Here is my Twig template (index.html.twig):
{% extends 'base.html.twig' %}
{% block body %}
<a href="123" class="test">Test</div>
{% endblock %}
{% block javascripts %}
{% javascripts '#AppBundle/js/jquery.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('.test').on('click', function(){
var id = jQuery(this).attr('href');
jQuery.post('{{path('task_ajax')}}',
{data: id},
function(response){
alert(response);
}
);
return false;
});
});
</script>
{% endblock %}
Here is my routing.yml file:
task_ajax:
pattern: /jobs
defaults: { _controller: AppBundle:Ajax:task }
requirements:
_method: POST
Here is my controller:
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class AjaxController extends Controller
{
public function taskAction() {
$request = $this->container->get('request');
$data = $request->query->get('data');
return new Response($data);
}
}
check routing order. Move Ajax route to first place.

Categories

Resources