I am trying to get users amount of coins saved to my flask project. So users are supposed to write in a input field how much coins they want to display, for instance "1200", then I want flask to receive that and print it on my table I have. I have done some research, and also tried copy a bit of code from my "contact" form, but no luck at all!
Here is my HTML code:
div class="search_div">
<form action="GET">
<input type="text" class="coins-box" placeholder="Amount of Coins" />
</form>
</div>
Here is my python code:
#app.route('/bflipper', methods=['GET', 'POST'])
def bFlipper():
if request.method == 'GET':
userInput = request.form['input']
return render_template('flipper.html', userInput=userInput)
I mainly want it to be stored into a variable on python, as I need to add some other stuff with that user input later on!
Make a global variable and assign value to it inside the function
my_value = ""
#app.route('/bflipper', methods=['GET', 'POST'])
def bFlipper():
if request.method == 'GET':
global my_value
my_value = request.form['input']
Related
How do I get the data from a WTForms form after submitting it? I want to get the email entered in the form.
class ApplicationForm(Form):
email = StringField()
#app.route('/', methods=['GET', 'POST'])
def index():
form = ApplicationForm()
if form.validate_on_submit():
return redirect('index')
return render_template('index.html', form=form)
<form enctype="multipart/form-data" method="post">
{{ form.csrf_token }}
{{ form.email }}
<input type=submit>
</form>
Each field has a data attribute containing the processed data.
the_email = form.email.data
Working with form data is described in the getting started doc.
The most probable place for you to do things with the Form.attrs is in the index function. I have added some conditional guards on the method param. You want to do different things if they are using GET or POST as well. There are other ways to do all of this but I didn't want to change too much at once. But you should think about it clearly this way. If I have no form data because I've just made the initial request, I'm going to be using GET. Once I render the form in the template, I'm going to be sending a POST (as you can see in the top of your template). So I need those two cases dealt with firstly.
Then, once the form is rendered and returned I will have data or no data. So dealing with the data is going to happen in the POST branch of the controller.
#app.route('/index', methods=['GET', 'POST'])
def index():
errors = ''
form = ApplicationForm(request.form)
if request.method == 'POST':
if form.is_submitted():
print "Form successfully submitted"
if form.validate_on_submit():
flash('Success!')
# Here I can assume that I have data and do things with it.
# I can access each of the form elements as a data attribute on the
# Form object.
flash(form.name.data, form.email.data)
# I could also pass them onto a new route in a call.
# You probably don't want to redirect to `index` here but to a
# new view and display the results of the form filling.
# If you want to save state, say in a DB, you would probably
# do that here before moving onto a new view.
return redirect('index')
else: # You only want to print the errors since fail on validate
print(form.errors)
return render_template('index.html',
title='Application Form',
form=form)
elif request.method == 'GET':
return render_template('index.html',
title='Application Form',
form=form)
To help, I'm adding a simple example from some of my working code. You should be able to follow it given your code and my walk through.
def create_brochure():
form = CreateBrochureForm()
if request.method == 'POST':
if not form.validate():
flash('There was a problem with your submission. Check the error message below.')
return render_template('create-brochure.html', form=form)
else:
flash('Succesfully created new brochure: {0}'.format(form.name.data))
new_brochure = Brochure(form.name.data,
form.sales_tax.data,
True,
datetime.datetime.now(),
datetime.datetime.now())
db.session.add(new_brochure)
db.session.commit()
return redirect('brochures')
elif request.method == 'GET':
return render_template('create-brochure.html', form=form)
I'm trying to submit form data to a route, similar to how a browser would, but am having trouble. I've simplified the code provided to the minimal I need to reproduce the problem. I'm probably not using a function I should or doing something else wrong but I can't find the answer in all the other posts I've searched. I don't want the data to be on the URL but rather accessible via request.form. I am using Python 2.7.9. I know the code shown below currently does NOT do what I want (it puts the formdata dictionary on the command line) and returns an endless loop because the formdata is never read. I understand this, I just did this to show that I'm trying to pass the formdata to the post function, I just don't know how to do it and also use redirect at the same time. If I'm reading the redirect documentation correctly it seems to say you can't do this. So is there some other function I can use that will pass the parameters to a URL and also provide the form data? I'm not using the parameters in the code below but my actual code has a similar function structure where I do use them. The main goal here is to have the same function (URL path) used when "choice" is or is not submitted via a form. Any help is appreciated. Thanks.
from flask import Flask, redirect, url_for, request, render_template
web_server = Flask(__name__)
#web_server.route("/test_<param1>_<param2>",methods=['POST','GET'])
def test1(param1,param2):
if request.method == 'GET':
choice1 = 'No choice made yet'
templateData = {'choice':choice1}
return render_template('form_page.html', **templateData)
elif request.method == 'POST':
if 'choice' in request.form:
choice1 = request.form['choice']
templateData = {'choice':choice1}
return render_template('form_page.html', **templateData)
else:
formdata = {'choice':'QQQ'}
p1='AAA'
p2='BBB'
# the following line is NOT what I want to do. See question
return redirect(url_for('.test1',param1=p1,param2=p2,data=formdata),code=307)
# run server
if __name__ == "__main__":
web_server.run(host='0.0.0.0',port=80,debug=True)
HTML:
Choice was {{choice}}<br><br>
<form method="post">
Make a choice:
<input type="text" name="choice"><br><br>
<input type="submit">
</form>
<form method="post">
Do anything else:
<input type="text" name="other"><br><br>
<input type="submit">
</form>
lets see if this is what you mean, see quick and dirty code below. Have a close look at the request.args statement, that is where you can get the variables stored in the url.
from flask import Flask, redirect, url_for, request, render_template
app = Flask(__name__)
#app.route('/',methods=['POST','GET'])
def test1():
if request.method == 'POST':
if 'choice' in request.form:
choice = request.form['choice']
return render_template('test.html', choice = choice)
else:
choice = 'QQQ'
p1 = 'AAA'
p2 = 'BBB'
return redirect(url_for('.test1',param1 = p1, param2 = p2, choice = choice))
choice = request.args.get("choice")
if choice == None:
choice = 'No choice made yet'
return render_template('test.html', choice = choice)
if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000,debug=True)
I've found a lot of into similar to this, but I just can't quite make it work. Basically, I've got a button, and upon pressing it, I want to fire that value back to my flask backend.
HTML Button:
<form action="" method="POST" ><button class="btn btn-danger" type="submit" name="delete" value="{{ item2 }}"><span class="glyphicon glyphicon-trash"></span> Delete</button> </form>
Python:
#app.route('/', methods=["GET","POST"])
def home():
if request.method == 'POST':
if request.form['delete'] == post_id:
(my sql login/cursor stuff....)
sql = "DELETE FROM test_table WHERE post_id = ?"
c.execute(sql, (post_id,))
return redirect("/")
As you can see, I'm populating the links (and subsequent variable) with jinja. It populated the button as it should, but sending it back to my python script isn't working.
UPDATE:
When I run this, I get an internal server error. I cannot see what the routing error is because I can't get debug to work (using wsgi/werkzeug).
I think we can conclusively say is that by not defining post id is why it's not working. So my question is, when the button sends data BACK to python, what value (and how) does python grab? is it name= or value= or something else?
Your problem is
request.form['delete'] == post_id
You get value from button (request.form['delete']) and try to compare with value in variable post_id which doesn't exists.
If you want to get value from button and assign to variable post_id then you need
post_id = request.form['delete']
or
post_id = request.form.get('delete')
and then you can use post_id in SQL query.
#app.route('/', methods=["GET","POST"])
def home():
if request.method == 'POST':
post_id = request.form.get('delete')
if post_id is not None:
(my sql login/cursor stuff....)
sql = "DELETE FROM test_table WHERE post_id = ?"
c.execute(sql, (post_id,))
return redirect("/")
I've been working on a form that sends data to a scraper and simultaneously generates a URL from form input. The returned templates works flawlessly, but the URL change ends up giving me the entire form in the URL and I can't figure out why.
The URL ends up looking like this:
http://localhost/options/%3Cinput%20id%3D%22symbol%22%20name%3D%22symbol%22%20type%3D%22text%22%20value%3D%22%22%3E
I'd like it to look like this:
http://localhost/options/ABC
Form class:
class OptionsForm(Form):
symbol = StringField('Enter a ticker symbol:', validators=[Required(), Length(min=1, max=5)])
submit = SubmitField('Get Options Quotes')
Views:
# Where the form data ends up
#app.route('/options/<symbol>', methods=['GET', 'POST'])
def options(symbol):
# Created this try/except so I could test functionality - for example, I can do 'localhost/options/ABC' and it works
try:
symbol = request.form['symbol']
except:
pass
return render_template('options.html', symbol=symbol, company_data=OS.pull_data(symbol, name=True))
# Where the form lives
#app.route('/', methods=['GET', 'POST'])
def index():
form = OptionsForm()
print(form.errors)
if form.validate_on_submit():
return redirect(url_for('options', symbol=form.symbol.data))
return render_template('index.html', options_form=form)
Template:
<div id="options_div">
<form method="POST" name="symbol_form" action="{{ url_for('options', symbol=options_form.symbol) }}">
{{ options_form.hidden_tag() }}
{{ options_form.symbol(size=10) }}
{{ options_form.submit(size=10) }}
</form>
Any help would be appreciated.
Try adding enctype='multipart/form-data' to the form tag. It looks like your form is using application/x-www-form-urlencoded, the default.
Edit OK so check this out. When your template is being rendered there is no value in that data attribute (In the url_for call). When not referencing the data attribute (as your original question shows), you're referencing the actual form element (which is why you see all of that html being passed in the url). Here are your options (that I see):
Use some kind of frontend javascript to bind the form's action attribute to the value in the input box. Something like angular would help for this (but is overkill if you don't use any of its other features).
Just have the form POST to /options (no symbol in url). Then, grab the symbol attribute from the form data.
I'm trying to use flask.g to store variables that can be accessed in other functions, but I don't seem to be doing something correctly. The application generates the following error when I try to access g.name: AttributeError: '_RequestGlobals' object has no attribute 'name'.
The documentation for flask.g says:
Just store on this whatever you want. For example a database
connection or the user that is currently logged in.
Here's a complete, minimal example that illustrates the error that I receive when trying to access the variable outside of the function it was created in. Any help would be greatly appreciated.
#!/usr/bin/env python
from flask import Flask, render_template_string, request, redirect, url_for, g
from wtforms import Form, TextField
application = app = Flask('wsgi')
#app.route('/', methods=['GET', 'POST'])
def index():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
name = form.name.data
g.name = name
# Need to create an instance of a class and access that in another route
#g.api = CustomApi(name)
return redirect(url_for('get_posts'))
else:
return render_template_string(template_form, form=form)
#app.route('/posts', methods=['GET'])
def get_posts():
# Need to access the instance of CustomApi here
#api = g.api
name = g.name
return render_template_string(name_template, name=name)
class LoginForm(Form):
name = TextField('Name')
template_form = """
{% block content %}
<h1>Enter your name</h1>
<form method="POST" action="/">
<div>{{ form.name.label }} {{ form.name() }}</div><br>
<button type="submit" class="btn">Submit</button>
</form>
{% endblock %}
"""
name_template = """
{% block content %}
<div>"Hello {{ name }}"</div><br>
{% endblock %}
"""
if __name__ == '__main__':
app.run(debug=True)
The g object is a request-based object and does not persist between requests, i.e. g is recreated between your request to index and your request to get_posts.
Application Globals in Flask:
Flask provides you with a special object that ensures it is only valid for the active request and that will return different values for each request. In a nutshell: it does the right thing, like it does for request and session.
For persistent storage of tiny data between requests use sessions instead. You may (but should not) get away with storing the data in the app object directly for global (all sessions) application state, similar to what config does, if you find a really good reason to do so.
For more complex data use databases.
If you need to track authentication information, I'd suggest one of the Flask plugins like Flask-Login or Flask-Principal.
For example, we use Flask-Principal. It raises the identity-loaded signal when somebody authenticates (or it detects an authentication cookie). We then map their logged-in identity with a user in our database. Something like this:
# not actual code
#identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
user = Person.query.filter(Person.username==identity.person.username).one()
g.user = user
and then we can use g.user in any controller or template. (We're actually ripping a lot of this out, it was a easy, lazy hack that's caused more trouble than it's worth.)
If you don't want to use a module, there's a built-in signal you can hook into at the start of every request:
http://flask.pocoo.org/docs/tutorial/dbcon/
# This runs before every request
#app.before_request
def before_request():
g.user = your_magic_user_function()
and g.user would then be magically available everywhere.
I hope that helps!
Just use sessions in flask. In your case, you just want to save the user/name in your request and the easiest way is to use sessions.
from flask import session
app.secret_key = 'some key for session'
Then, your functions could be changed as below:
#app.route('/', methods=['GET', 'POST'])
def index():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
session['name'] = form.name.data
return redirect(url_for('get_posts'))
else:
return render_template_string(template_form, form=form)
#app.route('/posts', methods=['GET'])
def get_posts():
if 'name' in session:
name = session['name']
else:
name = "Unknown"
return render_template_string(name_template, name=name)
I will like to shed more light on the use of g global in storing data. g only store data with a request and when redirecting to another route, the g global is set back to null i.e it reset back to nothing. This means whatever set to g in one request can't be access in another request. Use sessions to store data that will be accessed across request.
One benefit of using g global is when connecting to a database to fetct a user. For example, may be the admin from the database. The admin can be store in the g global using the below method.
from flask import Flask, g
app = Flask(__name__)
#app.before_request
def text():
g.a = User.query.filter_by(email='admin#gmail.com')
#app.route("/getTrue", methods=['GET', 'POST'])
def getTrue():
form = UserForm()
if form.validate_on_submit():
if g.a == form.email.data:
return "Admin is logged in"
else:
return "User is logged in"
return render_template('login.html', form=form)
In the example above, the g can be use to save data which will be use in another request. I hope this help. Thanks