I am new to Flask and want to create a On/Off toggle button on my website. I was wondering if and how this is possible also including a dynamic label. The following picture shows what I have in mind:
I was thinking about using a wtfforms SubmitField but I don't quite know how to implement this dynamic behavior between my routes.py file and my html template. I was thinking something like this:
forms.py:
from flask_wtf import FlaskForm
from wtforms import SubmitField
class PowerSwitchForm(FlaskForm):
power_switch = SubmitField("ON")
routes.py:
from flask import render_template, flash, redirect, url_for
from app import app
from app.forms import PowerSwitchForm
#app.route('/power', methods=['GET', 'POST'])
def power():
power_switch = PowerSwitchForm()
if power_switch.power_switch.label.text == "ON" and power_switch.validate():
flash("Power has been turned ON")
power_switch.power_switch.label.text = "OFF"
return redirect(url_for('power')
elif power_switch.power_switch.label.text == "OFF" and power_switch.validate():
flash("Power has been turned OFF")
power_switch.power_switch.label.text = "ON"
return redirect(url_for('power')
return render_template('power.html', form0=power_switch)
power.html:
<!DOCTYPE html>
{% extends "base.html" %}
{% block content %}
<h2>Power switch</h2>
<form action="" method="post" novalidate>
{{ form0.hidden_tag() }}
{{ form0.power_switch() }}
</form>
{% endblock %}
You can use jquery to handle the desired operation when the toggle button is clicked. Also, if there is a backend process that should be performed when the button is toggled, ajax can be used. This answer demonstrates both. bootstrap-toggle is a library that enables simple implementation of a toggle. To use, copy the header tag values below:
Simple toggle that displays "toggled" or "untoggled":
<html>
<body>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"></script>
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
</head>
<input type="checkbox" class='toggle' checked data-toggle="toggle">
<div class='status'>Toggled</div>
</body>
<script>
$(document).ready(function() {
$('.toggle').click(function() {
var current_status = $('.status').text();
if (current_status === 'Untoggled'){
$('.status').html('Toggled');
}
else{
$('.status').html('Untoggled');
}
});
});
</script>
</html>
Toggle that triggers backend script for both "toggled" or "untoggled":
In the template, slightly change the script:
<script>
$(document).ready(function() {
$('.toggle').click(function() {
var current_status = $('.status').text();
$.ajax({
url: "/get_toggled_status",
type: "get",
data: {status: current_status},
success: function(response) {
$(".status").html(response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
Then, in your app, create a route /get_toggled_status:
#app.route('/get_toggled_status')
def toggled_status():
current_status = flask.request.args.get('status')
return 'Toggled' if current_status == 'Untoggled' else 'Untoggled'
This example does the same thing as the pure html/jquery solution, however, it does demonstrate how the backend can be communicated with when using the toggle.
I am also new to Flask. And here is the pure python code with flask that I've tried.
Looks it work.
in templates/demo.html :
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block content %}
<div class="page-header">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
in demo.py :
from flask import Flask, render_template, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import SubmitField
class PowerState(FlaskForm) :
state = SubmitField('OFF')
app = Flask(__name__)
Bootstrap(app)
app.config['SECRET_KEY'] = 'YOUR SECRET KEY'
#app.route('/', methods=['GET', 'POST'])
def home() :
form = PowerState()
if form.validate_on_submit() :
if form.state.label.text == 'OFF' :
PowerState.state = SubmitField('ON')
elif form.state.label.text == 'ON' :
PowerState.state = SubmitField('OFF')
return redirect(url_for('home'))
return render_template('demo.html', form=form)
then run :
flask run
Regards, Alex.Wu
Related
I'm trying to execute a def/python script from flask, when clicked on button... but can't seem to figure it out.
Here's my Python Code
from flask import Flask, redirect, url_for, render_template, request
import webbrowser
app = Flask(__name__)
#app.route("/")
def home():
return render_template("index.html")
def contact():
if "open" in request.form:
print("Test")
elif "close" in request.form:
print("Test 2")
return render_template('contact.html')
if __name__ == "__main__":
app.run(debug=True)
And here is my HTML Code
<html>
<head>
<title>Home page</title>
</head>
<body>
{% extends "base.html" %}
{% block title %}Home Page{% endblock %}
{% block content %}
<h1>Test</h1>
<input type="submit" name="open" value="Open">
<input type="submit" name="close" value="Close">
{% endblock %}
</body>
</html> ```
I don't know what is in {% block content %} but you need to have a form in order to call backend where you provide the url route that you want to call and the method you want to use (usually with forms it's POST). Also in the /contact endpoint you need to provide #app.route('/contact') and that it would accept POST request #app.route('/contact', methods=['POST']). Modify your python and HTML to look like this:
from flask import Flask, redirect, url_for, render_template, request, jsonify
import webbrowser
app = Flask(__name__)
#app.route("/")
def home():
return render_template("index.html")
#app.route('/contact', methods=['POST'])
def contact():
result = False
if "open" in request.form:
result = activate_lamp() # expecting True as a result of function
elif "close" in request.form:
result = deactivate_lamp()
return jsonify({'result': result}) # expecting True as a result of function
if __name__ == "__main__":
app.run(debug=True)
<html>
<head>
<title>Home page</title>
</head>
<body>
<h1>Test</h1>
<form action="{{ url_for('contact') }}" method="post">
<input type="submit" name="open" value="Open">
<input type="submit" name="close" value="Close">
</form>
</body>
</html>
The jsonify will return an object to the front end with default 200 response code. Then you can either do something with it or ignore it. The idea is that in the route you can call other functions, but you must return a valid HTTP response to the front-end, e.g. jsonify, or plain return '', 200 might be enough.
I have following Problem:
i want to send some data to Html from Python with button Click in HTML, but wenn i click the button it doesn't work at all.
Here is my code:
*
python.py:
from flask import Flask, render_template, flash, Markup, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('new.html')
#app.route('/SomeFunction', methods = ['POST', 'GET'])
def SomeFunction():
if request.method == 'GET':
text = 'Name'
print("result:")
return render_template("new.html",text = text)
if __name__ == '__main__':
app.run()
and here is my Html:
<!doctype html>
<html>
<head>
<title>The jQuery Example</title>
<div class="flashes">
{% for message in get_flashed_messages()%}
{{ message }}
{% endfor %}
</div>
<h2>jQuery-AJAX in FLASK. Execute function on button click</h2>
<script type="text/javascript" {{ url_for('static', filename='app.js')}}></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"> </script>
<script type=text/javascript> $(function() { $("#mybutton").click(function (event) { $.getJSON('/SomeFunction', { }, function(data) { }); return false; }); }); </script>
</head>
<body>
<input type = "button" id = "mybutton" value = "Click Here" />
<p>text: {{text}}</p>
</body>
</html>
So what i want is when i press the input button it will show the name what is in python defined. Maybe there are other ways what can make it works, but i need exactly in python.
Okay so passing variables from python flask to html is easy.
Import json
make a dictionary object with key whatever you want and assign your variable to that key
jobj = { 'name' : name }
Now dump this object as json and pass as argument
return render_template('htmlfile.html', res=json.dumps(jobj))
Now you would be able to access the res json in JavaScript in htmlfile.html
<Script>
var res = JSON.parse(' {{ res | safe }} ');
console.log(res.name);
</Script>
So I was starting out with Flask and thought of creating a Youtube search engine wherein I will be taking data from the user through Html from and send that data to Flask using Ajax.
Here is the code for my index html page:
{% extends "layout.html" %}
{% block content %}
<script type=text/javascript>
$(function() {
$("#echoText").keyup(function() {
$.ajax({
type: "GET",
url: $SCRIPT_ROOT + "/echo/",
contentType: "application/json; charset=utf-8",
data: { echoValue: $('input[name="echoText"]').val() },
success: function(data) {
$('#echoResult').text(data.value);
}
});
});
});
</script>
<strong>Enter a value to echo back:</strong>
<input type='text' size='10' id='echoText' name='echoText'>
<button type='button' id='submitBtn' name='submitBtn'>Submit via AJAX</button><br /><br />
<div id='echoResult'></div>
{% endblock %}
And here is my flask app python file:
from flask import Flask, jsonify, render_template, request
import youtube
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/echo/', methods=['GET'])
def echo():
ret_data = {"value":youtube.youtube_search(request.args.get('echoValue'))[1][0]["id"]["videoId"]}
data = jsonify(ret_data)
return data
if __name__ == '__main__':
app.run(port=5000, debug=True)
So right now I am able to transfer the data from Html page to flask but I some how want to use the data return a YouTube video embedded in my Html page. How can I do that?
I have a small Flask app which has three fields (Destination, Start Time and End Time). I'd like to use DatePicker widget to display the calender when selecting start and end dates.
With my current scripts the date widget doesn't spawn at all. What am I missing here?
app.py:
# -*- coding: utf-8 -*-
from flask.ext.wtf import Form
from wtforms import SubmitField, SelectField, DateField
from flask import Flask, render_template, request
from flask.ext.bootstrap import Bootstrap
from flask.ext.admin.form.widgets import DatePickerWidget
class GeneralForm(Form):
destination = SelectField(choices = data)
start_time = DateField('Start at', widget=DatePickerWidget())
end_time = DateField('End at', widget=DatePickerWidget())
submit = SubmitField('Submit')
#app.route("/", methods=['GET', 'POST'])
def index():
form = GeneralForm(request.form)
if request.method == 'POST':
destination = form.destination.data
start_time = form.start_time.data
end_time = form.end_time.data
return render_template('page.html', form=form)
else:
return render_template('index.html', form=form)
bootstrap = Bootstrap(app)
if __name__ == '__main__':
app.run(debug=True)
index.html:
<link rel="stylesheet"
href="{{url_for('.static', filename='mystyle.css')}}">
<link rel="stylesheet"
href="{{url_for('.static', filename='datepicker.css')}}">
<link rel="javascript"
href="{{url_for('.static', filename='main.js')}}">
<link rel="javascript"
href="{{url_for('.static', filename='bootstrap-datepicker.js')}}"
<form action="#" method="post">
{{ form.destination }}
{{ form.start_time(class='datepicker') }}
{{ form.end_time(class='datepicker') }}
{{ form.submit }}
</form>
Flask-Admin's DatePickerWidget() basically adds data-date-format="YYYY-MM-DD" data-role="datepicker" attributes to an input field. After that a custom JavaScript function located in flask_admin/static/admin/js/form.js activates the Bootstrap-Datepicker widget on these fields.
So you need to include this script in your template (or write your own).
Add this line at the top of your template, which includes a helper macro:
{% import 'admin/static.html' as admin_static with context %}
and then you can include the form.js via adding these lines into your template (this script requires moment.js as well):
<script src="{{ admin_static.url(filename='vendor/moment.min.js') }}"></script>
<script src="{{ admin_static.url(filename='admin/js/form.js') }}"></script>
Note: You can also use the Bootstrap-Datepicker js and css files shipped with Flask-Admin. See the form_css() and form_js() macros in flask_admin/templates/bootstrap3/admin/lib.html and copy the corresponding lines into your template.
Have you declared the flask-bootstrap base.html reference file at the top of your page?
{% extends "bootstrap/base.html" as wtf %}
You can then initiate your form in your page by simply adding in the following
{{ wtf.quick_form(form) }}
Im trying to get a basic app working in Django that incorporates AJAX.
The app will take a domain name and will then send it to the server, which will do a dns lookup on it and then send the response back via AJAX to the client.
Views
from django.http import *
from django.shortcuts import render_to_response
from django.template import RequestContext
import sys
import os
import socket
def main(request):
if request.method == 'POST':
dig_input = request.POST['digInput']
digoutput = socket.gethostbyname(dig_input)
return render_to_response('digajax.html', {'response': digoutput}, context_instance=RequestContext(request))
else:
return render_to_response('digajax.html', context_instance=RequestContext(request))
URLs
url(r'^digajax$', 'digajax.views.main'),
Templates
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.2.js'></script>
<script type="text/javascript">
function send_request(){
$.get(location.href, function(data){
$("#output").html(data.output);
});
}
</head>
<body>
<form method="post" name="diginput form" action="/digajax">
{% csrf_token %}
<input name="digInput" id="digInput" type="text">
<input type="button" onclick="send_request();" value="Request this page with AJAX">lookup</input>
</form>
{% if response %}
<div id="output">
<p>{{ response|linebreaksbr }}</p>
</div>
{% else %}
<p>no</p>
{% endif %}
</body}
</html>
Without AJAX everything is working. Now that I want to use AJAX Im not what what code I should add to each section.
Any help would be really appreciated...............
Django provides an method on the request object your view is passed which will tell you whether the request was made via XmlHttp, request.is_ajax().
If that method returns true, you probably want to return only the fragment of the page you want to update, instead of the whole page.
If that method returns false, you probably want to return the entire page, since the user either has JavaScript turned off, or there was some type of error which caused the view to be requested normally.
So, your view should look like:
def main(request):
if request.method == 'POST':
dig_input = request.POST['digInput']
digoutput = socket.gethostbyname(dig_input)
if request.is_ajax():
return HttpResponse("<p>%s</p>" % digoutput)
else:
return render(request, 'digajax.html', {
'response': digoutput
})
else:
return render(request, 'digajax.html')
Your JavaScript code should be look like:
<script type="text/javascript">
function send_request(){
$.get(location.href, function(data){
$("#output").html(data);
});
}
</script>