my bottle app.py looks something like:
#route('/submit/<var>')
def submit(var):
# do action
redirect("/")
and i have a simple html button which redirects to the required page when clicked through
onclick="window.location.href='/submit/value'"
but this causes the whole page to effectively refresh by going to the link and then coming back straight away, putting the user to the top of the page and so on.
How can i get it to do the bottle backend without refreshing?
In your template:
<button type="button" onclick="onSubmit('Value')">Sumbit!</button>>
<p id="response"></p>
<script>
function onSubmit(value) {
var myRequest = new Request('/submit/' + value);
var myInit = { method: 'PUT' };
fetch(myRequest, myInit).then(function(response) {
return $("#response").text(response);
});
}
</script>
In the python side
#put("/submit/<val>")
def submit(val):
return "Yay it worked!"
Related
I have been prototyping a web server using flask and recently switched to ReactJS for my front end. I am trying to display an image that is stored on my server to my web page as follows:
#app.route("/graph" methods=['POST'])
def displayGraph():
return send_from_directory("graphDir", "graph.png")
Before switching to React, if I went to /graph, the image would display no problem. Now, however, the webpage never redirects to /graph and displays the byte code for the image instead of the image itself. What do I need to change to properly display my image on my React web page? For reference, my React code is below:
export default class App extends React.Component {
constructor (props) {
super(props);
//Initialize your state here
this.state = {
results: "",
};
//bind functions here
this.handleChange = this.handleChange.bind(this);
}
//this is called after everything is created
componentDidMount() {
}
//add functions here
//changes state of checkbox
handleChange(event) {
const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
this.setState({
[event.target.name]: value
});
}
submit() {
$.ajax({
type: "POST",
contentType: "application/json",
url: "/graph",
});
}
render() {
return (
<div>
<div className="big title">Title</div>
<input type="button" onClick={() => this.submit()} value="Submit" className="button"/>
</div>
);
}
}
If you are able to get the byte code of the image using the ajax call, you can add an <img> to your render and set the src to the image's byte code.
<image src = 'data:image/jpeg;base64,' + 'your-image-data'/>
I'm looking to display a constantly-changing python variable (that's read from a websocket server) onto a HTML file, currently i'm using a Django tag as it follows:
templatetags/mytag.py
from django import template
register = template.Library()
current_value = 0
#register.filter
def c_value(placeholder):
return current_value
#more code that modifies current_value reading from a websocket server
index.html
{% load mytag %}
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( {{ placeholder|c_value }} );
}
, 1000);
}
mytimer();
</script>
#some code from the website
<span id="stuff">Holder</span>
However naturally '{{ placeholder|c_value }}' only outputs the first ever value of 'current_value', which is 0 in this case, and so the source code of index.html ends up being:
source code after '{{ placeholder|c_value }}'
<script>
function mytimer() {
setInterval(function(){
$('#stuff').html( 0 );
}
, 1000);
}
mytimer();
</script>
Which is not desired since we would like to print the changing-value of 'current_value' each second.
What is the normal approach for these kind of dynamic texts? Many thanks!
There are a few things you'll need to do to accomplish this behavior.
Set up a URL that returns the value you're interested in. For instance, set up your website so that the URL http://example.com/c_value returns a response with the correct information. It's usually a good idea to return the response in a JSON format; in Django, you can use the JsonResponse class to do this. Suppose you return the text:
{
"c_value": "foo"
}
Change your page so that instead of loading in a variable from a template, it makes a request to the address that you set up. If you're using jQuery, you can use the $.ajax function to do this (or $.getJSON, which is just a shorthand function for $.ajax with only JSON data). You'll probably end up with something like this inside of your timer, assuming that the JSON returned matches the example I gave in step 1. (data will contain the JSON object that you sent from the server).
$.ajax({
dataType: "json",
url: "http://example.com/c_value",
success: function(data) {
$('#stuff').html(data["c_value"]);
}
});
I have a dynamically created table with data from a django model. This table is displaying additional information about each data_element.
In the last column there should either
be a button displayed for each row, which will run the script with additional keywords from that specific data_element, without reloading or freezing the page.
If the script is still running (can take hours) there should be progress icon displayed and
if the script has already finished, there should be a button displayed, redirecting to an results.html
How can I program that with django?
Currently I am executing a script manually, but for that I am redirecting to another template with the args to parse and when the script is executed (with call_command('my_script', *args) the page freezes until the script ends.
<form action="{% url 'calculate' element_id %}">
<input class="btn btn-primary-custom" id="submit" type="submit" value="run script">
</form>
I tried to insert the code from this post:
Django button ajax click
But when I click on that button, nothing happens. What do I have to do, to create that table?
EDIT
the function for my button currently looks like this:
$(document).ready(function(){
$('.calculate-btn').bind('click', function(){
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var btn-data= $(this).attr('btn-data');
var csrftoken = getCookie('csrftoken');
$.ajax({
type: 'POST',
url : "/run/",
dataType: "html",
data : {'csrfmiddlewaretoken': csrftoken, 'btn-data':btn-data},
success: function(data, status, xhr){
console.log("SUCCESS")
},
error: function(data, status, xhr){
console.log("ERROR")
}
});
return false;
});
});
and my view gets called from a button click:
<input id="{{item.id}}" class='calculate-btn' name="update_log" type="button" value="Run Script" btn-data={{ item.id }}>
How can I now dynamically change the button, while the script is still running?
You will need a way to launch async tasks, and a way to get the task status, and then add quite some js/ajax code to launch the task and update your table accordingly.
For the first two parts, the canonical solution is celery.
Another, less recommended way to do that (less recommended, but probably easier to setup than celery) is to simply spawn a child, detached process which will complete the job in the background and store the status and results somewhere (e.g. in your database or in a memory storage like redis).
The main disadventage is that you lose control of what is happening in the child process. Depending on your project - if you don't care about the process control - it may turn out to be better solution.
I have a website written using django that has text entry, voting, and a table display of the entries sorted by age and votes, all on one page:
http://www.highscore.a2hosted.com/index/
Now I would like to have separate entry, voting, and table pages, and I have started with the voting page. This works well, and votes are added to entries in the underlying sqlite3 database, but I have to refresh the table page (index) manually.
Is there an easy way to force update, or at a last resort, reload of the table data in the table (index) url from actions in the voting url or views.py?
I include code snippets below:
views.py
def index(request):
context = {
'latest_entry_list': Entry.objects.order_by('-pub_date')[:10],
'high_entry_list': Entry.objects.order_by('-score','-pub_date')[:10],
'high_entry': Entry.objects.order_by('-score','-pub_date')[:1],
'low_entry_list': Entry.objects.order_by('score','-pub_date')[:10],
'voting_entry_list': Entry.objects.unvoted_or_random(),
}
return render(request, 'entries/index.html', context);
def voteup(request):
voting_id = request.GET.get('voteid')
if request.method=='GET':
v = Entry.objects.get(pk=voting_id)
v.score +=1
v.voted=True
v.save()
else:
pass
return HttpResponse('done')
voting.html
<div id="Vote" class = "high">
<div style="text-align: center">
{% for entry in voting_entry_list %}
<li>{{ entry.text }} {{ entry.score }}</li>
<p>
<input type="submit" id="voteid" name='voteid' value="{{ entry.id }}" autofocus value="" onfocus="this.value = this.value;" class = "transparent"/>
<script>
$(document).ready(function() {
$("#voteid").bind("keydown", function(e) { //input type=id above
if (e.keyCode == 38) {
var text = $("#voteid").val();
var args = {'voteid':text};
$.get("/voteup/", args).done(function(data) {
console.log("message: " + data);
location.reload();
});
return false;
}
});
});
</script>
{% endfor %}
</div>
EDIT for code based on accepted answer;
Thanks, I took your first option and I did this on the tables page:
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.body,
success: function(s,x){
$(this).html(s);
}
});
}, 1000);
</script>
Is there an easy way to force update, or at a last resort, reload of
the table data in the table (index) url from actions in the voting url
or views.py?
What you are looking for is a way to let the browser automatically check for updates from the back end, and then update itself without "refreshing".
It is similar to how notifications work on StackOverflow. If you get a new message or a change in your reputation, the top bar updates itself without you having to refresh.
To accomplish this, you have two options:
You can poll the database every x seconds from your front end, and then trigger an update. This is basically an automated way to hit "F5".
You can open a socket so that your front end is updated when the backend is updated.
Either way will require you to add some front end logic. For option #2, you can use django-socketio an app that uses the socket.io library to implement the WebSocket protocol which is a way to open sockets (think of it like a permanent connection), between the browser and the backend.
On the back end you would create a channel, on which you would transmit messages. The browser will subscribe to these channels and listen. As soon as the message is transmitted from your backend, the browser can trigger an update (for example, add a new row to a table, popup a warning, etc.)
try to do this :
from django.core.urlresolvers import reverse
def voteup(request):
voting_id = request.GET.get('voteid')
if request.method=='GET':
v = Entry.objects.get(pk=voting_id)
v.score +=1
v.voted=True
v.save()
return redirect(reverse('index'))
#redirect to you index and refrech the data
else:
pass
I am just getting started into python and flask (for the raspberry pi). I want a web application that would execute some python code to pan and tilt a camera and display a video stream.
My code up until now for flask is:
from flask import Flask, render_template
import time
import serial
#ser = serial.Serial('/dev/ttyUSB0',9600)
app = Flask(__name__)
#app.route('/')
#app.route('/<cmd>') #each button in my html redirects to a specified directory
def execute(cmd=None):
if cmd == "down":
print "Moving Down"
#ser.write("D")
if cmd == "up":
print "Moving Up"
#ser.write("U")
if cmd == "left":
print "Moving Left"
# ser.write("L")
if cmd == "right":
print "Moving Right"
#ser.write("R")
if cmd == "reset":
print "Reseting.."
#ser.write("X")
return render_template("main.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True)
The problem is my code relies on the each button redirecting to a new directory, while this does work well, it refreshes the page each time which means my embedded video reloads and buffers again. Is there a better way of detecting a button press and then executing python code using flask?
I would split it out into two routes to make it easier to see what you have to do:
LEFT, RIGHT, UP, DOWN, RESET = "left", "right", "up", "down", "reset"
AVAILABLE_COMMANDS = {
'Left': LEFT,
'Right': RIGHT,
'Up': UP,
'Down': DOWN,
'Reset': RESET
}
#app.route('/')
def execute():
return render_template('main.html', commands=AVAILABLE_COMMANDS)
#app.route('/<cmd>')
def command(cmd=None):
if cmd == RESET:
camera_command = "X"
response = "Resetting ..."
else:
camera_command = cmd[0].upper()
response = "Moving {}".format(cmd.capitalize())
# ser.write(camera_command)
return response, 200, {'Content-Type': 'text/plain'}
Then in your template you just need to use some JavaScript to send off the request:
{# in main.html #}
{% for label, command in commands.items() %}
<button class="command command-{{ command }}" value="{{ command }}">
{{ label }}
</button>
{% endfor %}
{# and then elsewhere #}
<script>
// Only run what comes next *after* the page has loaded
addEventListener("DOMContentLoaded", function() {
// Grab all of the elements with a class of command
// (which all of the buttons we just created have)
var commandButtons = document.querySelectorAll(".command");
for (var i=0, l=commandButtons.length; i<l; i++) {
var button = commandButtons[i];
// For each button, listen for the "click" event
button.addEventListener("click", function(e) {
// When a click happens, stop the button
// from submitting our form (if we have one)
e.preventDefault();
var clickedButton = e.target;
var command = clickedButton.value;
// Now we need to send the data to our server
// without reloading the page - this is the domain of
// AJAX (Asynchronous JavaScript And XML)
// We will create a new request object
// and set up a handler for the response
var request = new XMLHttpRequest();
request.onload = function() {
// We could do more interesting things with the response
// or, we could ignore it entirely
alert(request.responseText);
};
// We point the request at the appropriate command
request.open("GET", "/" + command, true);
// and then we send it off
request.send();
});
}
}, true);
</script>
I've got the same problem, and the answer is simple using ajax XmlHttpRequest:
// send a request, but don't refresh page
xhttp = new XMLHttpRequest();
xhttp.open("GET", "your script action", true);
xhttp.send();
Here's a small example, calling current script with parameters "like", embedded in a function:
function likeStuffs()
{
// send a request, but don't refresh page
xhttp = new XMLHttpRequest();
xhttp.open("GET", "?like", true);
xhttp.send();
}
You can simply do this with help of AJAX... Here is a example which calls a python function which prints hello without redirecting or refreshing the page.
In app.py put below code segment.
//rendering the HTML page which has the button
#app.route('/json')
def json():
return render_template('json.html')
//background process happening without any refreshing
#app.route('/background_process_test')
def background_process_test():
print "Hello"
return "nothing"
And your json.html page should look like below.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type=text/javascript>
$(function() {
$('a#test').bind('click', function() {
$.getJSON('/background_process_test',
function(data) {
//do nothing
});
return false;
});
});
</script>
//button
<div class='container'>
<h3>Test</h3>
<form>
<a href=# id=test><button class='btn btn-default'>Test</button></a>
</form>
</div>
Here when you press the button Test simple in the console you can see "Hello" is displaying without any refreshing.