Pass slider value to bottle route function - python

I am trying to run a code but one part is not working, where I need to pass the value from a slider. I can see the value in html page but I can not pass it to inputRange() where I need to run some commands.
I've tried to isolate only the code which work with slider. Could you please let me know how can I pass the slider value to val_slide? Thanks.
Code:
from bottle import route, run, template
IP_ADDRESS = '192.168.0.80'
PORT = 8080
#route('/')
def hello():
return '<b>Test</b>'
#route('/remote')
def remote():
return '''<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
<script>
$(document).ready(function() {
$('#inputRange').on('change mouseup', function(){
var val_slide ='inputRange';
$.ajax({
url: '/remote/inputRange',
type: 'GET',
data: {command:val_slide},
});
});
});
</script>
<style></style>
</head>
<body>
<div data-role="page">
<div data-role="main" class="ui-content">
<form>
<div style="text-align:center">
<label for="switch">Test</label>
<div class="slidecontainer">
<input id="inputRange" type="range" min="0" max="100" step="1" value="20" class="slider" name='data'>
<output name="inputRange"/output>
</div>
</form>
</div>
</div>
</body>
</html>'''
#route('/remote/inputRange')
def inputRange():
print val_slide
# use val_slide value
return 'inputRange'
try:
run(host = IP_ADDRESS, port= PORT)
except(KeyboardInterrupt):
print('Done!')
quit()

To access query parameters from GET request you should import request and use request.query to access to values by name:
from bottle import route, request
#route('/remote/inputRange')
def inputRange():
val_slide = request.query.command
print(val_slide)
return val_slide
I'm not big specialist in JavaScript, but as far as I know, to send actual value (not just static text) you need to replace val_slide static text assignment with reading of value:
var val_slide = this.value;

Related

In flask, paragraph is overwriting again but I want to print them separately

Snippet of HTML:
<div class="split left" >
<div class="centered">
<div class="container">
<p>Hi!</p>
</div>
<div class="darker">
<p>{{message}}</p>
</div>
<form action="{{ url_for('index')}}" method="post">
<input type="text" name="client" placeholder="Enter Message" class="text" id="message">
<button class="glow-on-hover">Send</button>
</form>
Snippet of FLASK code:
#app.route("/")
def start():
return render_template("index.html")
#app.route("/", methods=["POST"])
def index():
message = request.form.get("client")
return render_template("index.html", message=message)
Whenever I enter value and press send button it overwrites but I want to print a new paragraph each time I press send button. The list can not be useful in my opinion because it is something like a chat app. So the list will only display one recipient's message. Any effective and easy way???
here I have recreated your code and it seems working fine. Usually, the form refreshes the current page which leads to overwriting of contents.
Python Code:
#app.route("/")
def start():
return render_template("index.html")
#app.route("/message")
def index():
message = request.args.get("msg")
return message
HTML Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function textGen(){
$.get('/message', {"msg": document.getElementById('message').value }).done(function(data){
document.getElementById("text").innerHTML += `<p>${data}</p>`;
})
}
</script>
</head>
<body>
<div class="split left">
<div class="centered">
<div class="container">
<p>Hi!</p>
</div>
<div class="darker" id="text">
</div>
<input type="text" name="client" placeholder="Enter Message" class="text" id="message">
<button class="glow-on-hover" onclick="textGen()">Send</button>
</body>
</html>
In both the components, I have created msg handler in flask and msg sender in javascript using jquery. So this solution will work in your scenario. Take a look and please write to me if you face any errors or difficulties in making this code work. And I'm not using the form so it will prevent overwriting.

Unable to use Jinja templating to pass variable from Starlette backend to Javascript frontend

I am using starlette ASGI framework and want to render an HTML response.
Using a dummy route below to test passing a variable to javascript frontend.
#app.route('/error')
async def server_error(request):
template = 'analyze_response.html'
context = {"request": request}
return templates.TemplateResponse(template, context, data=75)
This is my 'analyze_response.html' file:
<html lang='en'>
<head>
<meta charset='utf-8'>
<link rel='stylesheet' href='../static/style.css'>
<script src='../static/client.js'></script>
<link rel="stylesheet" href="../static/cmGauge.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="../static/cmGauge.js"></script>
<script type="text/javascript">
var data = {{ data|tojson }}
</script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div>
<div class='center'>
<div class='title'>Sentiment Analysis of Movie Reviews</div>
<div class='content'>
<form action="/analyze" class="form" method="post">
<div class="form-group">
<textarea rows = "10" cols = "100" name = "review_text"></textarea><br>
</div>
<div class='analyze'>
<input type="submit" class="form-submit-button" value="Analyze">
</div>
</form>
<div id="gaugeDemo" class="gauge gauge-big gauge-green">
<div class="gauge-arrow" data-percentage="40"
style="transform: rotate(0deg);"></div>
</div>
<script type="text/javascript">
$('#gaugeDemo .gauge-arrow').cmGauge();
$('#gaugeDemo .gauge-arrow').trigger('updateGauge', myFunc());
</script>
</div>
</div>
</div>
</body>
As per some of the answers, I tried everything but it's still not working.
Getting below error:
File "app/server.py", line 125, in server_error
return templates.TemplateResponse(template, context, data=data) TypeError: TemplateResponse() got an unexpected keyword argument
'data'
Can you please let me know what the issue is? Thanks.
You need to pass it inside the context variable:
#app.route('/error')
async def server_error(request):
template = 'analyze_response.html'
context = {'request': request, 'data': 75}
return templates.TemplateResponse(template, context)

How to upload a file and populate parts of the website with its content?

There are related questions here and here but they don't solve my problem.
Let's say I have a file testdata.csv like this:
A,B
1,3
2,4
and I want the user allow to upload the file and then - just for simplicity - display its content on the same page without affecting any other elements on this page. So my desired outcome would look like this:
How would I do this? I found a couple of approaches that use a form to load the file and send its (modified) content back (to e.g. download it) but I struggle to find a solution to pass the JSON response back to modify the page (here: add the table).
This is my entire code:
from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json
# Initialize the Flask application
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/_get_table', methods=["POST", "GET"])
def get_table():
# how to catch the file here and send its content back?
# file = ????
# print(file)
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])
# if I use a form, I can use
# file = request.files['myfile']
# however, how do I then send the JSON response?
if __name__ == '__main__':
app.run(debug=True)
and my index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-center text-muted">Some great stuff</h3>
</div>
<hr class="mb-4">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div><br><br>
<button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>
<hr class="mb-4">
<table id="pretty_table" class="table table-striped"></table>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var table = null;
$('#upload_document').bind('click', function() {
$.getJSON('/_get_table', {
// what to pass here?
}, function(data) {
if (table !== null) {
table.destroy();
table = null;
$("#pretty_table").empty();
}
table = $("#pretty_table").DataTable({
data: data.my_table,
columns: data.columns
});
});
return false;
});
$('.custom-file-input').on('change', function() {
let fileName = $(this).val().split('\\').pop();
$(this).next('.custom-file-label').addClass("selected").html(fileName);
});
});
</script>
</body>
</html>
#charlietfl in the comments and this link got me on the right track. One can use FormData and then an .ajax call to achieve the desired outcome. So the important parts of above's link are (the complete files can be found below):
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div>
</form>
and
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
and
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/_get_table",
data: data,
processData: false,
The processData: false, is important to prevent jQuery form transforming the data into a query string as explained in the link above.
On the flask site, we can then easily retrieve the file by doing:
file = request.files['myfile']
df = pd.read_csv(file)
which turns the .csv into a pandas dataframe. Clearly, there should be checks etc before doing this.
The entire HTML page index_formdata.html would look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-center text-muted">Some great stuff</h3>
</div>
<hr class="mb-4">
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div>
</form><br><br>
<button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>
<hr class="mb-4">
<table id="pretty_table" class="table table-striped"></table>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var table = null;
$("#upload_document").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
// disabled the submit button
$("#upload_document").prop("disabled", true);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/_get_table",
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
if (table !== null) {
table.destroy();
table = null;
$("#pretty_table").empty();
}
table = $("#pretty_table").DataTable({
data: data.my_table,
columns: data.columns
});
$("#upload_document").prop("disabled", false);
},
error: function (e) {
alert(e.responseText);
console.log("ERROR : ", e);
$("#upload_document").prop("disabled", false);
}
});
});
$('.custom-file-input').on('change', function() {
let fileName = $(this).val().split('\\').pop();
$(this).next('.custom-file-label').addClass("selected").html(fileName);
});
});
</script>
</body>
</html>
the flask file as follows:
from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json
# Initialize the Flask application
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index_formdata.html')
#app.route('/_get_table', methods=["POST", "GET"])
def get_table():
# catch file from the form; if you have several files, just make several requests (access by name)
file = request.files['myfile']
df = pd.read_csv(file)
return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])
if __name__ == '__main__':
app.run(debug=True)
and the testdata.csv file
A,B,C
1,3,123
2,4,456

python flask render_template html did not render correctly

I'm building a python flask app implementing user log in , after user log in succefully, it will redirect to userHome.html
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Python Flask Bucket List App</title>
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
 
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
    <link href="../static/css/signup.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="header">
            <nav>
                <ul class="nav nav-pills pull-right">
                    <li role="presentation" class="active">Logout
                    </li>
                </ul>
            </nav>
            <h3 class="text-muted">Python Flask App</h3>
        </div>
 
        <div class="jumbotron">
            <h1>Welcome Home !!</h1>  
        </div> 
        <footer class="footer">
            <p>© Company 2015</p>
        </footer>  
    </div>
</body>
</html>
and the python code to perform return render_template('userHome.html')
in validateLogin :
#app.route('/validateLogin',methods=['POST'])
def validateLogin():
cursor = None
try:
_username = request.form['inputName']
_password = request.form['inputPassword']
# connect to mysql
conn = mysql.connect()
cursor = conn.cursor()
cursor.callproc('sp_validateLogin',(_username,_password))
data = cursor.fetchall()
if len(data) > 0:
return render_template('userHome.html')
else:
return render_template('error.html', error = "Wrong Username or
Password")
except Exception as e:
return render_template('error.html',error = str(e))
finally:
if cursor:
cursor.close()
conn.close()
and the signin.js :
$(function(){
$('#btnSignIn').click( function(){
$.ajax({
url: '/validateLogin',
data: $('form').serialize(),
type: "POST",
success: function(response){
console.log(response);
},
error: function(error){
console.log(error);
}
});
});
});
and finally the signin.html:
!DOCTYPE html>
<html lang="en">
<head>
<title>Sign In</title>
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
<link href="../static/signup.css" rel="stylesheet">
<script src="/static/js/jquery-3.1.1.js"></script>
<!--<script src="/static/js/jquery-3.1.1.min.map"></script>-->
<script src="/static/js/signin.js"></script>
</head>
<body>
<div class="container">
<div class="header">
<nav>
<ul class="nav nav-pills pull-right">
<li role="presentation" >Home</li>
<li role="presentation" class="active">Sign In</li>
<li role="presentation">Sign Up</li>
</ul>
</nav>
<h2 class="text-muted">Release Control System</h2>
</div>
<div class="jumbotron">
<h1>Log In</h1>
<form class="form-signin">
<label for="inputName" class="sr-only">Name</label>
<input type="name" name="inputName" id="inputName" class="form-control" placeholder="Name" required autofocus>
<!--<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>-->
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required>
<button id="btnSignIn" class="btn btn-lg btn-primary btn-block" type="button">Sign in</button>
</form>
</div>
<footer class="footer">
<p>Copyright 2017 Foxconn CABG © All Rights Reserved.</p>
</footer>
</div>
</body>
</html>
but when I log in successfully it does not direct to the userHome.html page, it showed all html entities instead. Meaning the templates are working but the browser is treating wrongly.
I've tried many tricks like:
headers = {'Content-Type': 'text/html'}
return make_response(render_template('userHome.html'),200,headers)
but it still returns html entities, not html page.
This has confused me for days, thanks in advance.
Since I don't know how to send a redirect request to ajax and execute it. I will simply share the way I do things.
# Python Code
#app.route('/login')
def login():
# check if user is not logged in then render the login form
if user_not_logged_in():
return render_template('login_form.html')
# if user logged in, then redirect to userHome
else:
return redirect(url_for('userHome'))
from flask import jsonify
#app.route('/validateLogin', methods=['POST'])
def validateLogin():
# do some stuff and check for validation
if stuff_goes_well:
return jsonify({'data': 'success'})
else:
return jsonify({'data': 'failure'})
#app.route('/userHome')
def userHome():
# check if user is logged in
if logged_in_user_session_exists():
return render_template('userHome.html')
else:
# user is not logged in so redirect him to the login page
return redirect(url_for('login'))
# jQuery code
$.ajax({
url: "/validateLogin",
type: "POST",
dataType: "json",
data: data_here,
success: function(response){
if(response.data == 'success'){
# success was sent so the user logged in successfully, redirect to user home
window.location.replace('/userHome');
}else{
# there was an error in the logging in
alert('there was an error!');
}
}
});
To sum it up in a few words: simply send your data with ajax to Python. then let Python handle verification and the analysis of the data. then if all goes well, tell jQuery " hey it's all cool here " ( which is represented by the 'success' string we send ). if something was wrong then we tell jQuery that we had a problem hence the 'failure' string we send. then in jQuery we act upon the string that was sent. if it was success, then we redirect the user to the desired URL ( which is /userHome in this case ). if failure was sent then we say there was an error.
Please notice that these python checks are important so the user just doesn't type "/userHome" in the URL and be able to just view the page while he is not logged in.
I hope you find this useful.

Markdown with Syntax highlighting in Flask

I am trying to implement the same stack overflow text-area with syntax highlighting in Python and have come this far but i am not able to get it working.
app.py
from flask import Flask, render_template, request
import preview
app = Flask(__name__)
#app.route('/',methods=['GET','POST'])
def index():
if request.method == 'POST':
markdown_content = request.args.get['wdd-input']
post_preview = preview.markdown(markdown_content['data'])
return render_template('test.html', result=post_preview)
if request.method == 'GET':
return render_template('demo.html')
if __name__ == '__main__':
app.run()
preview is something which does syntax highlighting and its based upon Pygments.
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PageDown Demo Page</title>
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/static/css/highlighting.css">
<link rel="stylesheet" type="text/css" href="/static/css/demo.css" />
<script type="text/javascript" src="/static/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="/static/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/static/js/hycus-textarea.js"></script>
<script type="text/javascript" src="/static/js/Markdown.Editor.js"></script>
<script type="text/javascript">
(function (m) {
m(document).ready(function () {
m('textarea.wmd-input').TextAreaResizer();
});
})(jQuery);
</script>
</head>
<body>
<div class="container">
<div id="pagedwon">
<div id="tabnav">
<ul class="nav nav-tabs" id="markdown_tab" style="padding: 0 10px; margin-bottom: 10px;">
<li class="active">Edit</li>
<li>Preview</li>
</ul>
</div>
<div class="tab-content">
<div class="tab-pane active" id="edit">
<div class="wmd-panel">
<div id="wmd-button-bar"></div>
<textarea class="wmd-input" id="wmd-input" rows="10" name="text-input">
This is the *pagedown* editor.
------------------------------
**Note**: Just plain **Markdown**, except that the input is sanitized: **HTML** is not allowed.
</textarea>
</div>
<script type="text/javascript">
(function () {
var pagedown_editor = new Markdown.Editor();
pagedown_editor.run();
})();
</script>
<script type="text/javascript">
(function (m) {
m("#markdown_tab a").click(function () {
if (m(this).html() == "Preview"){
var markdown_content = m("#wmd-input").val();
if (!markdown_content) {
m("div#markdownpreview").html("Empty Markdown Content.");
} else {
content_to_preview = {
"data": markdown_content
}
m.post("/", content_to_preview)
.success( function(preview_content){
if (preview_content == 'None'){
m("div#markdownpreview").html("No content received.");
} else {
m("div#markdownpreview").html(preview_content);
}
})
.error( function () {
m("div#markdownpreview").html("Sorry, error occurred. Please retry.");
});
}
}
});
})(jQuery);
</script>
</div>
<div class="tab-pane markdown-body" id="markdownpreview">
Loding preview content ...
</div>
</div>
</div>
</div>
</body>
</html>
This is log from the console:
127.0.0.1 - - [26/Jun/2014 20:25:01] "POST / HTTP/1.1" 500 -
How to get it working, please help. I am new to Flask.
First, request.args is for query string parameters, but you are sending over data via POST. You should be using request.form instead.
Second, MultiDict.get is a function, and does not support the __getitem__ protocol (which is the cause of your 500 error).
Third, as #Doobeh points out in the comments, you are sending the data over under the key data, but you are trying to access it via the key "wdd-input" - this will result in a BadRequest error.
Finally, the value extracted from request.form will be a string (which does not support strings as __getitem__ values) - and you don't need it anyway, as you already have the entire string.
A re-worked version of your POST portion:
if request.method == 'POST':
markdown_content = request.form.get('data', 'No content yet ...')
post_preview = preview.markdown(markdown_content)
return render_template('test.html', result=post_preview)

Categories

Resources