Render template in Flask from ajax call - javascript

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)

Related

Uncaught ReferenceError: data is not defined at HTMLDocument.<anonymous

I am trying to render a Json Response on a html site using AJAX but i keep getting the error:
Uncaught ReferenceError: data is not defined
at HTMLDocument.<anonymous
JsonResponse in Question:
["[53.50119612705815, -1.1270833894501477] -> [53.34474, -3.01101]", "[53.50119612705815, -1.1270833894501477] -> [53.34474, -3.01101]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[53.50119612705815, -1.1270833894501477] -> [53.42705, -0.94339]"]
Html file with AJAX and JS:
<div class="'row">
<div id="test">
<h1> Test </h1>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function(){
$.ajax({
type: 'POST',
dataType: 'json',
url: '/network/dispatch_data/',
data: data,
success: function(response) {
console.log(response);
$('#test').append(response.data);
}
});
});
</script>
{% endblock %}
When i inspect element in my browser, the error points to the data: data being the source of the error. Any idea what i'm doing wrong? I can view the url perfectly with the json response but making it show with ajax is proving a problem
You are sending data as the body of your request, but first you have to defined the object you are sending to API
<div class="row">
<div id="test">
<h1> Test </h1>
</div>
</div>
{% endblock %}
{% block js %}
<script>
const data = {
bar: [1, 2, 3],
foo: false
}
$(document).ready(function () {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/network/dispatch_data/',
data: data,
success: function (response) {
console.log(response);
$('#test').append(response.data);
}
});
});
</script>
{% endblock %}

Following a tutorial I got a view retuning None instead because is_ajax is not working

I just started with ajax but can't seem to find the fix for this. I think it might have to do with the comment_id vs the blog_id. (followed this tutorial: https://www.youtube.com/watch?v=VoWw1Y5qqt8&list=PLKILtxhEt4-RT-GkrDkJDLuRPQfSK-6Yi&index=39&ab_channel=AbhishekVerma).
This is what my views.py looks like
def like_comment(request):
comment = get_object_or_404(Comment, id=request.POST.get("comment_id"))
blog = get_object_or_404(BlogPost, id=request.POST.get("blog_id"))
comments = Comment.objects.filter(post=blog, reply=None)
if request.user in comment.likers.all():
comment.likers.remove(request.user)
else:
comment.likers.add(request.user)
context = {
"comments": comments,
"blog_post": blog,
"body": markdown2.markdown(blog.body),
"comment_form": CommentForm(),
}
if request.is_ajax():
html = render_to_string('blog/like_section.html',
context, request=request)
return JsonResponse({'form': html})
This is a snippet of my HTML
{% if request.user.is_authenticated %}
<form action={% url 'like_comment' %} method="POST">
{% csrf_token %}
{% if user in comment.likers.all %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Like</button>
{% else %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Dislike</button>
{% endif %}
{% else %}
<div><small class="comment_time">Login to Like</small></div>
{% endif %}
</form>
</div>
<small class="comment_time">{{ comment.total_likes }}
Likes</small>
And this is the javascript:
$(document).ready(function (event) {
$(document).on('click', '#like', function (event) {
event.preventDefault();
var pk = $(this).attr('value');
$.ajax({
type: "POST",
url: '{% url "like_comment" %}',
data: { 'blog_id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}' },
dataType: 'json',
success: function (response) {
$('#like_section').html(response['form'])
console.log($('#like_section').html(response['form']));
},
error: function (rs, e) {
console.log(rs.responseText);
},
});
});
});
I'm getting the following error:
Picture
I would start to check if the request header contains HTTP_X_REQUESTED_WITH='XMLHttpRequest'. You can do that with the debug function of the browser (e.g. firefox). Maybe your JS library does not send this header.
see the Django documentation:
https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.HttpRequest.is_ajax
def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
HttpRequest.is_ajax():
Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. Most modern JavaScript libraries send this header. If you write your own XMLHttpRequest call (on the browser side), you’ll have to set this header manually if you want is_ajax() to work.
If a response varies on whether or not it’s requested via AJAX and you are using some form of caching like Django’s cache middleware, you should decorate the view with vary_on_headers('X-Requested-With') so that the responses are properly cached.

Using ajax to pass post data to python

HTML
{% if todo_array %}
<ul>
{% for TodoList in todo_array %}
<li class="listItems" name="listItem" id="item{{ forloop.counter }}" onClick = "myFunction({{ forloop.counter }})" >
{{ TodoList.todo_text }}
</li>
{% endfor %}
</ul>
{% else %}
<p> Add some Todo's !! </p>
{% endif %}
Javascript
var csrftoken = getCookie('csrftoken');
function myFunction(value){
console.log("clicked")
$.ajaxSetup({
headers: { "X-CSRFToken": getCookie("csrftoken") },
type:"POST",
{% load static %}
url:"{%url 'home'%}",
data: {
id : value
},
success: function(data) {
console.log('success',data);
},
});
}
Python
def home(request):
if request.method == 'POST':
todelete = request.POST.get('id')
print(todelete)
return render(request, 'home/mainList.html', context)
I'm trying to send the ID from html using javascript into python by making an ajax call. However the post data isn't working. How can I fix my code?
Edit.
Getting a server internal error 500 now.
Urls.py
urlpatterns = [
path('', views.home, name='home'),
path('logout', views.logout_attempt, name='logout')
]

Django + AJAX - POST 404 (Not Found)

I'm trying to implement a like functionality in my Django app using AJAX but, when I try to do that I'm getting an POST http://localhost:8000/forum/like/ 404 (Not Found). All I wanna do is to add/remove users from the likes list without refreshing the entire page.
views.py
#require_POST
def toggle_like(request):
if request.method == "POST":
user = request.user
slug = request.POST.get('slug', None)
question = get_object_or_404(Question, slug=slug)
if question.likes.filter(id=user.id).exists():
question.likes.remove(user)
else:
question.likes.add(user)
context = {'likes-count': question.likes.count}
return HttpResponse(json.dump(context), content_type='application/json')
urls.py
from django.urls import path
from . import views
app_name = 'forum'
urlpatterns = [
path('like/', views.toggle_like, name='toggle-like'),
]
question.html
{% block javascript %}
<script>
$('#like').click(() => {
$.ajax({
method: 'POST',
url: "{% url 'forum:toggle-like' %}",
data: {
'slug': $(this).attr('name'),
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
dataType: 'json',
success: (response) => {
alert(response.message);
},
error: (response, error) => {
alert(response.responseText);
}
})
})
</script>
{% endblock %}
{% block content %}
<p>Likes: {{ question.likes.count }} <input type="button" id="like" name="{{ question.slug }}" value="Like" /></p>
{% endblock %}

Flask Dynamic data update without reload page

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>

Categories