Flask app is running correct function, but not rendering template
Question:
I have a flask app with a template. I am attempting to send via post several items collected by javascript when the user clicks a button. When I post my data to /confirm, the print statement executes, but the render_template function does not render anything, my web browser stays on the /likes page.
Here is the web_interface.py:
#!/bin/python3
from flask import Flask, render_template, request, url_for, redirect
import twitter as twitter
from dataclasses import dataclass
import json
app = Flask(__name__)
form_data = {}
tweet_data = {}
@app.route("/")
def index():
return render_template("index.html")
@app.route("/likes", methods=['POST','GET'])
def likes():
if request.method == 'POST':
tweet_url = request.form['inputTweetURL1']
liking_user_list = twitter.liking_users_lookup_by_url(tweet_url)
return render_template("likes.html", liking_user_list=liking_user_list)
else:
return render_template("likes.html")
@app.route('/confirm', methods=['POST'])
def confirm():
#block_list = json.loads(request.data.decode())["data"]
# print("Print the data: {}".format(foo))
block_list = json.loads(request.data.decode())['data']
print(block_list)
return render_template("confirm.html", block_list=block_list)
app.run(host="0.0.0.0", port=80)
And here is the template:
{% extends 'base.html' %}
{% block content %}
<form method='POST'>
<div class="mb-3">
<label for="inputTweetURL1" class="form-label">Tweet URL</label>
<input type="text" class="form-control" name="inputTweetURL1" id="inputTweetURL1"
aria-describedby="inputTweetURL1Help">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="scrollme">
<table class="table table-striped">
<!-- Table headers -->
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">User ID</th>
<th scope="col">Profile URL</th>
<th scope="col">Follower Count</th>
<th scope="col">Verified Status</th>
<th scope="col">Block User</th>
</tr>
</thead>
<!-- Table body -->
<tbody class="table-group-divider">
<!-- For loop logic of jinja template -->
{%for user_data in liking_user_list%}
<!-- Table rows -->
<tr>
<th scope="row">1</th>
<td>{{user_data['name']}}</td>
<td>{{user_data['id']}}</td>
<td><a href="https://twitter.com/{{ user_data.username }}">https://twitter.com/{{ user_data['username']
}}</a></td>
<td>{{user_data['public_metrics']['followers_count']}}</td>
<td>{{user_data['verified']}}</td>
<td><a><button type="button" class="btn btn-primary toggle-button">Block</button></a></td>
{%endfor%}
</tr>
</tbody>
</table>
<button type="submit" id="danger-report" class="btn btn-primary">Submit</button>
<input type="hidden" name="hiddenInput" id="hiddenInput">
</div>
<script>
$(document).ready(function () {
// Add click event listener to a button with an ID of "danger-report"
$('#danger-report').click(function () {
// Get all the buttons with the btn-danger class
var dangerButtons = $('.btn-danger');
// Filter out the rows that contain the danger buttons
var dangerRows = dangerButtons.parents('tr');
// Define an empty list to store the contents of the <td> elements
var tdContents = [];
// Log the number of danger rows and their contents to the console
dangerRows.each(function () {
var name = $(this).find('td:eq(0)').text(); // Get the text content of the first <td> element in the row
var id = $(this).find('td:eq(1)').text(); // Change '1' to the index of the <td> you want to log
var url = $(this).find('td:eq(2)').text(); // Change '1' to the index of the <td> you want to log
var followers = $(this).find('td:eq(3)').text(); // Change '1' to the index of the <td> you want to log
var verified = $(this).find('td:eq(4)').text(); // Change '1' to the index of the <td> you want to log
var item = { "name": name, "id": id, "url": url, "followers": followers, "verified": verified }
tdContents.push(JSON.stringify(item));
});
//console.log(tdContents)
// Join the contents of the tdContents array with commas
var dataToSend = tdContents.join(',');
var r = new XMLHttpRequest();
r.open("POST", "http://127.0.0.1/confirm", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
//alert("Success: " + r.responseText);
console.log("Sent");
};
// Send data in below way from JS
r.send(JSON.stringify({ "data": dataToSend }));
});
});
</script>
{% endblock %}
I can’t figure out why when posting r.send the template isn’t rendered. Any ideas?
UPDATE:
Here is the updated routing:
@app.route('/confirm', methods=['POST','GET'])
def confirm():
if request.method == 'POST':
#block_list = json.loads(request.data.decode())["data"]
# print("Print the data: {}".format(foo))
block_list = json.loads(request.data.decode())['data']
#print(block_list)
print('youre posting, it worked')
return render_template("confirm.html", block_list=block_list)
else:
block_list = json.loads(request.data.decode())['data']
print('youre gettin')
return render_template('confirm.html', block_list=block_list)
And here is the function where the POST request is sent. Is this where I need to do the redirecting?
var r = new XMLHttpRequest();
r.open("POST", "http://127.0.0.1/confirm", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
//alert("Success: " + r.responseText);
console.log("Sent");
//window.location.href = "/confirm"; // Redirect to /confirm
};
// Send data in below way from JS
r.send(JSON.stringify({ "data": dataToSend }));
window.location.href = "/confirm";
Answers:
You can simplify the logic by sending the ids of the selected rows to the /confirm
endpoint. Then let the endpoint figure our what data the ids represent and render it for you.
@app.route('/confirm', methods=['GET'])
def confirm():
args = request.args
ids = args.get('ids')
id_list = ids.split(',')
return render_template('confirm.html', id_list=id_list)
I have a flask app with a template. I am attempting to send via post several items collected by javascript when the user clicks a button. When I post my data to /confirm, the print statement executes, but the render_template function does not render anything, my web browser stays on the /likes page.
Here is the web_interface.py:
#!/bin/python3
from flask import Flask, render_template, request, url_for, redirect
import twitter as twitter
from dataclasses import dataclass
import json
app = Flask(__name__)
form_data = {}
tweet_data = {}
@app.route("/")
def index():
return render_template("index.html")
@app.route("/likes", methods=['POST','GET'])
def likes():
if request.method == 'POST':
tweet_url = request.form['inputTweetURL1']
liking_user_list = twitter.liking_users_lookup_by_url(tweet_url)
return render_template("likes.html", liking_user_list=liking_user_list)
else:
return render_template("likes.html")
@app.route('/confirm', methods=['POST'])
def confirm():
#block_list = json.loads(request.data.decode())["data"]
# print("Print the data: {}".format(foo))
block_list = json.loads(request.data.decode())['data']
print(block_list)
return render_template("confirm.html", block_list=block_list)
app.run(host="0.0.0.0", port=80)
And here is the template:
{% extends 'base.html' %}
{% block content %}
<form method='POST'>
<div class="mb-3">
<label for="inputTweetURL1" class="form-label">Tweet URL</label>
<input type="text" class="form-control" name="inputTweetURL1" id="inputTweetURL1"
aria-describedby="inputTweetURL1Help">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="scrollme">
<table class="table table-striped">
<!-- Table headers -->
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">User ID</th>
<th scope="col">Profile URL</th>
<th scope="col">Follower Count</th>
<th scope="col">Verified Status</th>
<th scope="col">Block User</th>
</tr>
</thead>
<!-- Table body -->
<tbody class="table-group-divider">
<!-- For loop logic of jinja template -->
{%for user_data in liking_user_list%}
<!-- Table rows -->
<tr>
<th scope="row">1</th>
<td>{{user_data['name']}}</td>
<td>{{user_data['id']}}</td>
<td><a href="https://twitter.com/{{ user_data.username }}">https://twitter.com/{{ user_data['username']
}}</a></td>
<td>{{user_data['public_metrics']['followers_count']}}</td>
<td>{{user_data['verified']}}</td>
<td><a><button type="button" class="btn btn-primary toggle-button">Block</button></a></td>
{%endfor%}
</tr>
</tbody>
</table>
<button type="submit" id="danger-report" class="btn btn-primary">Submit</button>
<input type="hidden" name="hiddenInput" id="hiddenInput">
</div>
<script>
$(document).ready(function () {
// Add click event listener to a button with an ID of "danger-report"
$('#danger-report').click(function () {
// Get all the buttons with the btn-danger class
var dangerButtons = $('.btn-danger');
// Filter out the rows that contain the danger buttons
var dangerRows = dangerButtons.parents('tr');
// Define an empty list to store the contents of the <td> elements
var tdContents = [];
// Log the number of danger rows and their contents to the console
dangerRows.each(function () {
var name = $(this).find('td:eq(0)').text(); // Get the text content of the first <td> element in the row
var id = $(this).find('td:eq(1)').text(); // Change '1' to the index of the <td> you want to log
var url = $(this).find('td:eq(2)').text(); // Change '1' to the index of the <td> you want to log
var followers = $(this).find('td:eq(3)').text(); // Change '1' to the index of the <td> you want to log
var verified = $(this).find('td:eq(4)').text(); // Change '1' to the index of the <td> you want to log
var item = { "name": name, "id": id, "url": url, "followers": followers, "verified": verified }
tdContents.push(JSON.stringify(item));
});
//console.log(tdContents)
// Join the contents of the tdContents array with commas
var dataToSend = tdContents.join(',');
var r = new XMLHttpRequest();
r.open("POST", "http://127.0.0.1/confirm", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
//alert("Success: " + r.responseText);
console.log("Sent");
};
// Send data in below way from JS
r.send(JSON.stringify({ "data": dataToSend }));
});
});
</script>
{% endblock %}
I can’t figure out why when posting r.send the template isn’t rendered. Any ideas?
UPDATE:
Here is the updated routing:
@app.route('/confirm', methods=['POST','GET'])
def confirm():
if request.method == 'POST':
#block_list = json.loads(request.data.decode())["data"]
# print("Print the data: {}".format(foo))
block_list = json.loads(request.data.decode())['data']
#print(block_list)
print('youre posting, it worked')
return render_template("confirm.html", block_list=block_list)
else:
block_list = json.loads(request.data.decode())['data']
print('youre gettin')
return render_template('confirm.html', block_list=block_list)
And here is the function where the POST request is sent. Is this where I need to do the redirecting?
var r = new XMLHttpRequest();
r.open("POST", "http://127.0.0.1/confirm", true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
//alert("Success: " + r.responseText);
console.log("Sent");
//window.location.href = "/confirm"; // Redirect to /confirm
};
// Send data in below way from JS
r.send(JSON.stringify({ "data": dataToSend }));
window.location.href = "/confirm";
You can simplify the logic by sending the ids of the selected rows to the /confirm
endpoint. Then let the endpoint figure our what data the ids represent and render it for you.
@app.route('/confirm', methods=['GET'])
def confirm():
args = request.args
ids = args.get('ids')
id_list = ids.split(',')
return render_template('confirm.html', id_list=id_list)