Flask Dynamic data update without reload page - javascript

i'm trying to create something like Google Suggest Tool (via suggest api http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q=query )
I'm listening input changes, and send data go GET:
$("#search_form_input").keyup(function(){
var some_var = $(this).val();
$.ajax({
url: "",
type: "get", //send it through get method
data:{jsdata: some_var},
success: function(response) {
},
error: function(xhr) {
//Do Something to handle error
}
});
After that i'm handling this data and send it to Google API and got response in Python:
#app.route('/', methods=['GET', 'POST'])
def start_page_data():
query_for_suggest = request.args.get('jsdata')
if query_for_suggest == None:
suggestions_list = ['',]
pass
else:
suggestions_list = []
r = requests.get('http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q={}&gl=in'.format(query_for_suggest), 'lxml')
soup = BeautifulSoup(r.content)
suggestions = soup.find_all('suggestion')
for suggestion in suggestions:
suggestions_list.append(suggestion.attrs['data'])
print(suggestions_list)
return render_template('start_page.html', suggestions_list=suggestions_list)
In Jinja trying to print it in HTML dynamically:
<label id="value_lable">
{% for suggestion in suggestions_list %}
{{ suggestion }}
{% endfor %}
</label>
But variable in Jinja doesn't update dynamically and print empty list.
How to print suggestions from list dynamically in HTML?

Working example:
app.py
from flask import Flask, render_template, request
import requests
from bs4 import BeautifulSoup
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/suggestions')
def suggestions():
text = request.args.get('jsdata')
suggestions_list = []
if text:
r = requests.get('http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q={}&gl=in'.format(text))
soup = BeautifulSoup(r.content, 'lxml')
suggestions = soup.find_all('suggestion')
for suggestion in suggestions:
suggestions_list.append(suggestion.attrs['data'])
#print(suggestions_list)
return render_template('suggestions.html', suggestions=suggestions_list)
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html>
<head>
<title>Suggestions</title>
</head>
<body>
Search: <input type="text" id="search_form_input"></input>
<div id="place_for_suggestions"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$("#search_form_input").keyup(function(){
var text = $(this).val();
$.ajax({
url: "/suggestions",
type: "get",
data: {jsdata: text},
success: function(response) {
$("#place_for_suggestions").html(response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
</script>
</body>
</html>
suggestions.html
<label id="value_lable">
{% for suggestion in suggestions %}
{{ suggestion }}<br>
{% endfor %}
</label>

Related

How do I get my ajax POST (preventDefault) to work?

I am trying to upload a csv file to a Flask server and I do not want the page to be reloaded, so I am trying to implement ajax. However, I cannot get it to work. Here is a minimal working example.
app.py
import os.path
from flask import Flask, render_template, request
app = Flask(__name__, static_url_path='', static_folder='static', template_folder='templates')
app.config['UPLOAD_FOLDER'] = './upload/'
#app.route("/", methods=["POST", "GET"])
def home():
if request.method == "POST":
f = request.files['todo']
f.save(os.path.join(app.config['UPLOAD_FOLDER'], 'upload.csv'))
return 'this should not be printed'
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
templates/index.html
<!DOCTYPE html>
<html>
<body>
<form method="post" id="todo-form" enctype="multipart/form-data">
<input type="file" name="todo" id="todo">
<button type="submit">submit</button>
</form>
<script src="https://code.jquery.com/jquery-3.5.1.js"
integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
crossorigin="anonymous"></script>
<script src="test.js"></script>
</body>
</html>
static/ajax.js
$(document).on('submit', '#todo-form', function(e) {
const fd = new FormData(this);
e.preventDefault();
$.ajax({
type: 'POST',
url: '/',
data: fd,
contentType: false,
processData: false,
complete: function() { alert('saved');},
})
});
The reloading action is now prevented, and the alert is now shown, but the file is not uploaded. Can someone tell me what I did wrong? Thank you very much!
As pointed out by Phil, this is caused by the storage of browser cache. The code works as intended once the cache is cleared.

Render template in Flask from ajax call

Having a tough time with this. I'm sending some data via Ajax to my Flask server route where it is being processed, with hopes to then render a new template with the processed data. The data seems to be flowing fine from my Javascript to my Flask server. (I am using JSGlue for Flask.url_for.) But as soon as it gets to "return render_template" it just dies. I get no traceback errors or anything. I've tried print() and console.log all over the place to get some kind of idea of what is killing it, but so far I've come up empty. Am I missing something obvious?
mypage.js
let c_list = [1,2,3....];
$.ajax({
url: Flask.url_for('get_genres'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(c_list),
success: function (data) {
console.log(data);
}
})
init.py
#app.route('/get_genres', methods=["GET", "POST"]
def get_genres():
if request.method == "POST":
categories = request.json
c = Querybuilder()
genres = c.genres_from_c(categories)
return render_template("genres.html", genres=genres)
index.html
<head>
{{ JSGlue.include() }}
</head>
<body>
{% block body %}
{% endblock %}
</body>
genres.html
{% extends "index.html" %}
{% block body %}
<div class="genre_list">
{% for genre in genres %}
<a href="#" src="{{ genres[genre] }}" class="unclicked" onclick="toggleClicked(this)">
<p>{{ genre }}</p></a>
{% endfor %}
NEXT
</div>
{% endblock %}
After A LOT of digging around, I finally managed to find a solution to this issue. Adding a success function to the ajax call that redirects to another route.
mypage.js
$.ajax({
url: Flask.url_for('genre_picks'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(genres),
success: function(response) {
window.location.href = response.redirect
}
});
init
#app.route('/genre_picks', methods=["POST", "GET"])
def genre_picks():
if request.method == "POST":
genres = request.json
return jsonify({'redirect': url_for("example", path=genres)})
#app.route('/example/<path>')
def example(path):
genres = path
return render_template("example.html", genres=genres)

Text not changing with render_template after adding Ajax in Flask App

I created a simple AJAX to send data to a flask route without refreshing the page, the data seems to get to the route but it isn't changing the text after render_template.
MyForm is a simple dropdown. I'm trying to display the text of the current selection after form submitted or button clicked without refreshing the page by using AJAX.
run.py
from flask import Flask, redirect, render_template, request, jsonify
from forms.myform import MyForm
import json
import plotly
import pandas as pd, numpy as np
server = Flask(__name__)
server.config.update(dict(
SECRET_KEY="powerfulsecretkey",
WTF_CSRF_SECRET_KEY="a csrf secret key"
))
#server.route("/", methods=["POST", "GET"])
def index():
form = MyForm()
choice = request.form.get('options')
if form.validate_on_submit():
choice = request.form.get('options')
print(choice)
return render_template("index.html", form=form, choice=choice)
if __name__ == "__main__":
server.run()
form
from flask_wtf import FlaskForm
import wtforms
class MyForm(FlaskForm):
options = wtforms.SelectField(label="State", choices=[("SF", "SF"),
("LA", "LA")])
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" id="fm" action="/">
{{ form.csrf_token }}
<div>{{ form.options}}</div>
</form>
<button type="submit" form="fm" value="Submit">Submit</button>
<div>{{ choice }}</div>
</body>
<footer>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$('form').on('submit', function(e){
$.ajax({
type: 'POST',
data:$('form').serialize(),
url: '/',
success: function(data) {
console.log(data);
},
error: function(jqXHR) {
alert("error: " + jqXHR.status);
console.log(jqXHR);
}
});
e.preventDefault();
});
// Inject our CSRF token into our AJAX request.
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", "{{ form.csrf_token._value() }}")
}
}
})
</script>
</footer>
</html>
Browser
Because you are a form submitted by ajax,The page is not re-rendered,Jinja2 is a rendering to take effect

Django: Ajax not receiving data from server response

I am pretty new to Django and I am trying to figure out how to add content dynamically coming from a python script without reloading a page.
Currently, I have two functions in my views.py file. One handles uploading a file (home), and the other handles calling a python script and handling the file (handle). The reason I separated it like this is because I want to sequentially populate a HTML table as the python script works with the uploaded file.
However, my ajax function is not receiving any data from the handle function's http response and I am not sure why. Neither the success nor the error functions are being called. This is really strange because the print statement in the handle function in views.py prints successfully with data.
Views.py
i=0
uploaded_file = None
def home(request):
if (request.method == 'POST'):
file_form = UploadFileForm(request.POST, request.FILES)
if file_form.is_valid():
global uploaded_file
uploaded_file = request.FILES['file']
print(uploaded_file)
else:
file_form = UploadFileForm()
return render(request, 'personal/home.html', {'form': file_form})
def handle(request):
# TODO make ajax wait for a response from 'home'
# so I don't have to wait for 1 second
time.sleep(1)
data = {}
data['Name'] = fileName(uploaded_file)
if(request.is_ajax()):
print(data) # prints succesfully
return HttpResponse(json.dumps(data),
content_type="application/json")
home.html
<script type = "text/javascript" language = "javascript">
function post_tables(data) {
alert(data)
}
$(document).ready(function(post_tables) {
$("#upload").click(function(event){
$.ajax( {
contentType: "application/json; charset=utf-8",
dataType: "json",
type: "get",
url:'/handler',
success: function(data) {
console.log("over here")
post_tables(data)
},
error: function(data) {
console.log("down here")
post_tables("error being thrown")
}
});
});
});
</script>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler', views.handle, name='handle'),
]
I explained the whole process ajax django to you. Perhaps your problem will be solved. good luck.
views.py
def handle(request):
if request.method == 'POST':
data = request.POST
field_example = data.get('field_example')
return JsonResponse(data)
else:
data = request.GET
field_example = data.get('field_example')
return JsonResponse(data)
home.html
<form id="upload">
{% csrf_token %}
<input type="text" name=field_example>
.
.
.
</form>
urls.py
urlpatterns = [
path(r'', views.home, name='home'),
path(r'handler/', views.handle, name='handle'),
]
js code in home.html:
$("#upload").submit(function (e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: "{% url 'handle' %}",
type: 'GET',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (data) {
console.log("over here")
post_tables(data)
},
error: function (data) {
console.log("down here")
post_tables("error being thrown")
}
});
});

Django Ajax Request Not Executing Properly

I'm trying to send an ajax request to a view called getToken(). I'm not sure why it isn't working. The console outputs "0: ". If I include the code inside my home view which is the page the call is being made from it will change the page to the json output and not the documentid I told it too. It doesn't call getToken at all even though its set up in the urls file to and my ajax url is set to that url.
When a user clicks the create token on his profile it will send a ajax request to getToken and return that output on the page in the output . Thus, the user can then give that key to his friends so they can add him or email or text the key.
HTML
{% load staticfiles %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script {% static "ChompMe/jquery.js" %}></script>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<script type="text/javascript">
$(document).ready(function() {
$("#create_token").click(function() {
var csrf = '{{ csrf_token }}';
$.ajax({
type: 'POST' ,
url: '/gettoken',
datatype: 'json' ,
async: true,
data:{
csrfmiddlewaretoken: '{{ csrf_token }}',
create_token: 'create_token',
},
success: function(json) {
console.log(csrf);
console.log(json.message);
document.getElementById('output').innerHTML = (json.message);
},
error : function(xhr,errmsg,err) {
console.log(xhr.status + ": " + xhr.responseText);
document.getElementById('output').innerHTML = "Token:" + " Request Failed.";
}
});
});
});
</script>
<title>ChompMe
{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
<form method='POST' >
{% csrf_token %}
<button id='create_token' name = 'create_token' value='create_token' > Create Token </button>
</form>
<p id='output'>
Token:
</p>
</body>
</html>
Urls.py
urlpatterns = patterns('',
url(r'^$', 'django.contrib.auth.views.login'),
url(r'^logout/$', logout_page),
url(r'^accounts/login/$', 'django.contrib.auth.views.login'), # If user is not login it will redirect to login page
url(r'^register/$', register),
url(r'^home$', home),
url(r'^register/success/$', register_success),
url(r'^admin/', include(admin.site.urls)),
url(r'^gettoken$', getToken),
url(r'^[A-Za-z0-9_.]+$', friends),
)
Views.Py
#login_required
#csrf_protect
def getToken(request):
print 'getToken'
post_data = request.POST.copy()
username = request.user
if request.POST.has_key('create_token'):
datetimes = datetime.now()
enc_token = base64.urlsafe_b64encode(str(request.user) + str(datetimes))
token = enc_token
context = {'token':token}
return HttpResponse(json.dumps(context),content_type="application/json")
#login_required
#csrf_protect
def home(request):
print 'home'
post_data = request.POST.copy()
username = request.user
if request.POST.has_key('create_token'):
datetimes = datetime.now()
enc_token = base64.urlsafe_b64encode(str(request.user) + str(datetimes))
token = enc_token
context = {'token':token}
return HttpResponse(json.dumps(context),content_type="application/json")
user_data = UserProfile.objects.filter(username=str(request.user))
print user_data
context = {'user': request.user,
'user_data':user_data,
}
return render_to_response('home.html',context , RequestContext(request))
Change /gettoken to /gettoken/.

Categories