How to utilize bootstrap toggle with flask - python

This question is an extension of this question regarding using the Bootstrap toggle with flask.
My code for the toggle is as follows:
<div class='media'>
<div class='media-left'>
<div class='media-object'>
<div class='padding-right'>
<form action="/menu" method="post">
<input name="toggle" onclick="this.form.submit()" data-off="<i class='fa fa-times'></i> " data-on="<i class='fa fa-check'></i> " data-onstyle='success' data-size='large' data-style='ios' data-toggle='toggle' id='activate-toggle' type='checkbox' value="on">
<input name="toggle" type="hidden" value="off">
</form>
</div>
</div>
</div>
<div class='media-body'>
<div id='console-event'></div>
</div>
</div>
And my endpoint for the page is as follows:
#app.route('/menu', methods=['POST', 'GET'])
def get_callback():
if request.method == 'POST':
button = request.form['toggle']
print(button)
return render_template('dashboard.html')
However I am not able to get any response from my button.
I am very lost at this point. I have tried to copy the format of the question above however I still cannot get the button to print or even use the POST method.
Here are my questions:
How can I get a response from my button?
How do I save the orientation so that when the user logs back in the button is how they previously left it?
(I am using SQLAlchemy if this is of any importance.)
Any help would be greatly appreciated!
Thank you,
Jonah

It seems that the target of your form defined in action is incorrect. What I would try and do is change it to the following:
<form action="{{url_for('get_callback')}}" method="POST">
As for saving the toggled state, you might want to create a column in your db table with a default of off (or on) and then write some code to update the saved value for the switch state whenever a change is made to the toggle switch.
If anyone else has a better idea to store the state of the switch, I'd be interested to find out how.

First of all, you don't need this second hidden input. It's resulting in there being two values for toggle, which isn't what you want.
<input name="toggle" onclick="this.form.submit()" data-off="<i class='fa fa-times'></i> " data-on="<i class='fa fa-check'></i> " data-onstyle='success' data-size='large' data-style='ios' data-toggle='toggle' id='activate-toggle' type='checkbox' value="on">
<input name="toggle" type="hidden" value="off">
But more importantly, your code, as written would print to the console the value of button, then return to the user the HTML form input. Perhaps this would clear things up:
#app.route('/menu', methods=['POST', 'GET'])
def get_callback():
if flask.request.method == 'POST':
button = bool(flask.request.form.get('toggle', False))
return "Toggle value: %r" % (button,)
else:
return render_template('dashboard.html')
If you do that, and remove that hidden input that shouldn't be there, it'll show the user "Toggle value: True" or "Toggle value: False" depending on which is clicked.
Though I don't see, in your example, how the user could submit the form without toggling the checkbox.

i would try it like that
#app.route('/menu', methods=['GET','POST'])
def get_callback():
if request.method == 'POST':
print(request.form.get('toggle'))
return render_template('dashboard.html')
if it does not work with ('toggle') try ('checkbox')

Related

Flask routing does not give desired results, URL not getting appended for some instance

I am building a web-app using flask where I am trying to route some URLs
I have three routes with me
a) "/"
b) "/teacher"
c) "/student"
The routing works fine for "/" and"/student" The URL gets appended after clicking the submit button for student and"/student" gets appended in URL but on clicking the button associated with "/teacher" the URL doesn't gets appended and "/" page keeps on loading up.
Please help me out here and tell me what wrong I am doing
My Python code:
#app.route('/', methods=['GET', 'POST'])
def select():
return render_template("select.html")
#app.route('/teacher', methods=['GET', 'POST'])
def index():
return render_template("index_teacher.html", title="Faculty login")
#app.route('/student', methods=['GET', 'POST'])
def index1():
return render_template("index_student.html", title="Student login")
Part of my html code from select.html:
<form action="/teacher" method = "post">
<input type="submit" class="submit" value="Login as Teacher">
</form>
<br>
<form action="/student" method="post">
<input type="submit" class ="submit" value="Login as Student">
</form>
One more thing about the code, when I add a text box above the first submit button, both the button starts working and give desired results.
Thanks in advance!
I think you have just a little typo in the html. The input tag of teacher didn't close >.
<form action="/teacher" method = "post">
<input type="submit" class="submit" value="Login as Teacher">
</form>
<br>
<form action="/student" method="post">
<input type="submit" class ="submit" value="Login as Student">
</form>
EDIT:
In the case that the question was copied incorrectly, I don't know what should be wrong with your code. For me your sample code works just fine. So from my experience with flask and html forms the most common errors I made are the following, maybe it's one of them (the list may serve other too, so I will also add points that do not make sense for your case):
method name of two routes collide (e.g. both '/' and '/teacher' are assigned to function index, but that should give an error when starting the server, so not really possible)
an html tag is not closed properly, so the form in question is not parsed as a valid form (that was my guess with above answer, also makes sense with the text box, which may close the corrupt tag => in html an open tag is closed by the first following closing tag)
typo in the form action attribute (check the network tab in your browsers developer tools, maybe you get an error response to something like "taecher", which results in a redirect to "/", again not really plausible with the fact that it suddenly works when you add the text box)
typo in the route or the returned template (again not plausible with explained behavior with the added text box)
That's all I can think of at the moment. I hope it helps with the search. if you could add more of your html code, maybe I find something suspicious.

Sending checkbox value to flask

I have a form that looks like this:
<form id="settings" action="{{ url_for("load_settings") }}" method="post">
...
<label for="m_r">Interval 1</label>
<input type="text" name="morn_r" id="m_r">
<label for="d1_e">Enabled</label>
<input type="checkbox" name="d_enabled" id="d1_e" value="off" onclick="toggle_check(this)">
</form>
This is the toggle_check function:
function toggle_check(check) {
if (check.value=="on") {
check.value="off";
}
else {
check.value="on";
}
}
Here's my Python:
#app.route("/settings", methods=["POST", "GET"])
def load_settings():
if request.method == "POST":
settings = list(request.form.values())
print(settings)
return render_template("settings.html")
If I leave the text inputs empty but click the checkbox, here is what gets printed: [..., '', 'on']
Now, if I also leave the checkbox empty this is what gets printed: [..., '']. For some reason it doesn't add the value of the checkbox...
I don't know how to fix this. Could someone please help?
Thanks.
Stealing from this answer, the HTML 4 recommendation from W3C states:
Checkboxes (and radio buttons) are on/off switches that may be toggled by the user. A switch is "on" when the control element's checked attribute is set. When a form is submitted, only "on" checkbox controls can become successful.
So it's not anything to do with Flask as to why the checkbox value isn't there when unchecked. The browser won't serialize that form input into the request when the checkbox is unchecked.
What you could do though, is give the input some sensible value in the template:
<input type="checkbox" name="d_enabled" value="on">
And then in your Flask handler check for the presence of the value:
if request.form.get('d_enabled') == 'on':
# checkbox is checked
else:
# checkbox is not checked

Python Flask - Processing input obtained from front-end in the back-end

this is more of a question about where to find how I would do this rather than asking how to do this. I'm sure this is well covered, I'm just struggling to articulate the correct term which I could use to Google and find out the answer.
Anyway - I have a Python Flask web application. On a web page, there is an input box which requests user input. What I would like to happen, is for some magic to happen with the user input in the background. In my own scenario, I would like to take a URL, then use bs4 to pick off what I need and display this on the web page.
For simplicity, I'll ask for something for simple and I can then build on it from there: if I were to request the user to specify a number then press 'Submit', how could I multiply the number by 10?
If my code for the form was index.html:
<form class="form-horizontal" role="form" method="post" action="/">
{{ form.csrf_token }}
<fieldset>
<div class="form-group">
<label for="GetNum" class="col-lg-2 control-label">Enter Number</label>
<div class="col-lg-6">
<input type="text" id="GetNum" name="GetNum" class="form-control" value="">
</div>
<input class="btn btn-success" type="submit" value="Calculate">
</div>
</fieldset>
</form>
I noticed that I can get the input to print to a paragraph by <p>form.request.GetNum</p>.
Now for this question's example, the code for the backend functionality will be:
import math
GetNum = 10 #should be form.request.GetNum value
CalcResult = GetNum*1000
print CalcResult # or {{ CalcResult.data }} or something in index.html
My Controller (app.py) looks like:
#app.route('/', methods=['GET', 'POST'])
#login_required
def home():
error = None
form = PostForm(request.form) # unrelated to question, but will this clash?
if .. :
do something
return redirect(..)
else:
do something else..
return render_template(..)
My worry is that the home function will end up having a mass of code if I have to put the math function in there. So tl;dr, how would I implement a back end function within my code? (or please provide me with material to read, thank you!)
One other thing is I already have a form on my '/' page, will I have to rename the forms like form1 form2 because they will clash or will it be OK?
Elsewhere in your code base, either in the same file, or more likely
a module or package you could define that complicated task. Lets
create a simple module complicated.py in the same directory as your
other code, that then defines the complicated task:
def do_really_complicated_thing(info):
# lots of complicated steps
return really_complicated_data
Then in our view code, we can just use that instead of having it embedded:
from complicated import do_really_complicated_thing
#app.route('/', methods=['GET', 'POST'])
#login_required
def home():
error = None
form = PostForm(request.form)
if form.validate_on_submit() :
info = form.info.data
complicated_task = do_really_complicated_thing(info)
return render_template('something', results=complicated_task)
So, in short-- the terms you're looking for is packages and modules, they
help your code be neater and reusable.
As for clashing forms— you can just target the form to post to a specific route which just handles that form, which is much cleaner then then having to validate/parse different forms in a single route.

Pyramid app: How can I pass values into my request.route_url?

I have this in my views.py file as the view config for my home page:
#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
body = request.params['body']
page=Page(name,body)
DBSession.add(page)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return {}
Also, here is the form in the edit.pt template:
<form action="/view_page" method="post">
<div>
<input type="text" name="name"/>
</div>
<div>
<input type="text" name="body"/>
</div>
<label for="stl">Stl</label>
<input name="stl" type="file" value="" />
<input type="submit" name='form.submitted' value="Save"/>
</form>
Also in my init.py file I have
config.add_route('home_page', '/')
config.add_route('view_page', '/{pagename}')
right now when I submit the form it just tries to go to localhost:6543/view_page. This returns a 404 as there is no view_page resource or route leading to it. Instead I want it to go to localhost:6543/(the name of the page I just created aka the first input box in the form). How can I do this?
Edit: I am worried that something else may be telling it to route to view_page because I even tried changing it to
return HTTPFound(location=request.route_url('front_page',pagename=name))
And it still goes to /view_page. There is no route named front_page, so I would at least suspect it to throw an error.
Also, I would really appreciate it if you could tell me where you found the info. I have been looking at http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/api/request.html?highlight=request.route_url#pyramid.request.Request.route_url but can't seem to find use from it.
Edit: should I be using an asset specification instead of a path name? so
return HTTPFound(Location=request.route_url('tutorial:templates/view.pt','/{pagename}'))
Also, I am working through this article which seems very helpful with the syntax: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#urldispatch-chapter
I think your form should submit to "/", ie.
<!-- where your home_page route is waiting for the POST -->
<form action="/" method="post">
With the prior answers this now looks correct:
return HTTPFound(location=request.route_url('view_page', pagename=name))
My first guess is that it's location not Location as the argument to HTTPFound.
from the link you give
it's should be
return HTTPFound(location=request.route_url('view_page',pagename=name))
when you had add this route
config.add_route('view_page', '/{pagename}')
and set the variable name before
name= request.params['name']

How can I access the form submit button value in Django?

I have a Django project that, on one page, has multiple forms (in different tags) that can be submitted to have different effects. In all cases I want the user to be redirected back to the same page, so I use in my view the pattern of submitting the form and then redirecting to the original page. In at least one case, the only difference between two of the forms is the value of the submit button.
In my view I have the code (which is the first time my view function accesses the request.POST):
if request.POST['submit']=='Add':
#code to deal with the "Add" form
and in the template, the first form has a submit button like
<input type="submit" value="Add">
I thought this would work, but when I submit that form, I get an error at the line in view from above:
Key 'submit' not found in <QueryDict: {u'clientyear': [u'2012'], u'csrfmiddlewaretoken': [u'be1f2f051f09f6ab0375fdf76cf6a4d7'], u'ben': [u'123405']}>
Obviously, this does not have a 'submit' key or any key with the value corresponding to the submit button I clicked. So, since this does not work, how can access the value of the submit button or tell which of the forms has been submitted?
Submit is an HTML Form structure... You must use name attribute of form objects as follows... In your template:
<form>
...
<input type="submit" name="list" value="List Objects" />
</form>
<form>
...
<input type="submit" name="do-something-else" value="Do Something Else" />
</form>
In your view:
if 'list' in request.POST:
# do some listing...
elif 'do-something-else' in request.POST:
# do something else
One thing to keep in mind to prevent confusion. The name of the submit button will not show if there is only a single button in the form.
#template.html
<form action="..." method="post">
<input type="submit" name = "first_button" value="Add">
</form>
#view.py
...
'first_button' in request.POST #False
#template.html
<form action="..." method="post">
<input type="submit" name = "first_button" value="Add">
<input type="submit" name = "second_button" value="Remove">
</form>
#view.py
...
'first_button' in request.POST #True if you clicked on that button
I'm little bit late but here is the solution
Problem you are facing
Your are trying to get Button name but getting the initial value of button that is not correct way.
HTML Code
<input type="submit" value="Add">
Python Code/View.py
if request.POST['submit']=='Add':
#code to deal with the "Add" form
Solution
First find button name in request.POST dictionary if exist then get their value.
HTML Code
Add name of your button and their value.
<input type="submit" value="Add" name="add_object">
Views.py
You can find the button name in request.POST dictionary
if request.POST['submit'] == 'add_object':
# Both ways to deal with it
if 'add_object' in request.POST:
Extra Stuff
We have two forms on a page.
First form have 2 buttons with same name subjects but different values fav_HTML and fav_CSS.
Second form also have 2 buttons with same name tutorials but different values
Tutorials_HTML and Tutorials_CSS.
<form action="" method="post">
Form 1
<button name="subject" type="submit" value="interview_HTML">HTML</button>
<button name="subject" type="submit" value="interview_CSS">CSS</button>
</form>
<form action="" method="post">
Form 2
<button name="tutorials" type="submit" value="Tutorials_HTML">HTML</button>
<button name="tutorials" type="submit" value="Tutorials_CSS">CSS</button>
</form>
views.py
We can handle different forms, check which button is clicked then getting their values and do something.
if 'subject' in request.POST: # this section handle subject form (1st Form)
#now we can check which button is clicked
# Form 1 is submitted , button value is subject now getting their value
if 'interview_HTML' == request.POST.get('subject'):
pass
# do something with interview_HTML button is clicked
elif 'interview_CSS' == request.POST.get('subject'):
pass
# do something with interview_CSS button is clicked
elif 'tutorials' in request.POST: #this section handle tutorials form (2nd form)
#now we can check which button is clicked
# Form 1 is submitted , button name is tutorials now getting their value
if 'Tutorials_HTML' == request.POST.get('tutorials'):
pass
# do something with fav_HTML button is clicked
elif 'Tutorials_CSS' == request.POST.get('tutorials'):
pass
# do something with fav_CSS button is clicked

Categories

Resources