Flask: User input [POST] - python

When a user submits input, I'm trying to execute a script that takes the user's input as a parameter and redirects the user back to the home page. When I run the script below, everything seems to work with the exception of the redirection. When I hit submit in the web browser, I get No data submitted.
from flask import Flask, render_template, redirect, request
from Index_generator import index_generator
from Yelp_api import request_yelp
#app.route('/home_city',methods = ['POST'])
def home_city():
CITY=request.form['city']
request_yelp(DEFAULT_LOCATION=CITY) #This function executes the script
return redirect('/')

What if use url_for with redirect?
from flask import Flask, render_template, redirect, request, url_for
from Index_generator import index_generator
from Yelp_api import request_yelp
#app.route('/', methods = ['GET'])
def home():
return 'Hello World'
#app.route('/home_city',methods = ['POST'])
def home_city():
CITY=request.form['city']
request_yelp(DEFAULT_LOCATION=CITY) #This function executes the script
return redirect(url_for('home'))

Related

Is it possible to execute a function after return statement in flask?

I have a time-consuming function that I want to run however, I don't want the user to keep waiting. This is my current code:
from flask import Flask, render_template, request, url_for, redirect, session
app = Flask(__name__)
#app.route('/', methods=["POST", "GET"])
def index():
my_function():
"""
execute codde
"""
my_function()
return render_template('index.html')
I want to run something like this:
#app.route('/', methods=["POST", "GET"])
def index():
my_function():
"""
execute codde
"""
return render_template('index.html')
my_function()
The myFunction is in the same page and it works perfectly fine.
Obviously this isn't possible but I just want to know how to return render_template('index.html') first and then call the function?
flask-executor provides a lightweight way to do this.
In your case, it might look like this:
from flask import Flask, render_template, request, url_for, redirect, session
app = Flask(__name__)
executor = Executor(app)
#app.route('/', methods=["POST", "GET"])
def index():
executor.submit(my_function)
return render_template('index.html')
my_function will be executed asynchronously, and index will continue to run immediately, letting you respond to the request by rendering the template without waiting for my_function to finish running.
If you need more guarantees, like scalability (tasks could execute on other computers) or reliability (tasks still execute if the webserver dies), you could look into something like Celery or RQ. Those tools are powerful, but generally require much more configuration then the flask-executor example above.
You can "yield" it.
from flask import Flask, render_template, request, url_for, redirect, session
app = Flask(__name__)
#app.route('/', methods=["POST", "GET"])
def index():
my_function():
"""
execute codde
"""
yield render_template('index.html')
my_function()
In this way the function "return" something but will not stop and call the "my_function" function and all the code after this.
For more info I suggest THIS LINK from GeekForGeek

Supress Redirecting by triggering a form action using Flask [duplicate]

This question already has an answer here:
Redirect back in Flask
(1 answer)
Closed 2 years ago.
I would like to use flask to define the action for a button. However, after triggering the action, I will automatically be redirected. E.g. having a button definition using the following html:
<html>
<body>
<form action="/do_something" method="post">
<button>Do something!</button>
</form>
</body>
</html>
And the action handling by the given python script:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def root():
return render_template("test_3.html")
#app.route("/do_something", methods=["POST"])
def something():
return 'Something'
app.run()
In this case, I start with the url "/". By clicking on the button "Do Something", I will automatically be redirected to the url "/do_something". What I actual want is:
Perform Action
Refresh the original page
Can some one help?
If the POST request to /do_something can occur on any page, I would recommend redirecting back to the request's referrer, which will "refresh" the page.
E.g
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
#app.route("/")
def root():
return render_template("test_3.html")
#app.route("/do_something", methods=["POST"])
def something():
# Do things
return redirect(request.referrer or request.host_url)
app.run()
Otherwise you can specify the page to go to with redirect() and url_for()
Example:
from flask import Flask, redirect, render_template, url_for
app = Flask(__name__)
#app.route("/")
def root():
return render_template("test_3.html")
#app.route("/do_something", methods=["POST"])
def something():
# Do things
return redirect(url_for("app.root"))
app.run()

flask getting an error, when importing recaptcha

I have a flask application, where I want to add a recaptcha field. I use it to verify, that an email can be sent. here is my code so far:
from flask import render_template, request, flash, session, url_for, redirect
from flask import Flask
from flask_mail import Mail, Message
from flask_recaptcha import ReCaptcha
app.config.update({'RECAPTCHA_ENABLED': True,
'RECAPTCHA_SITE_KEY':
'6LdJ4GcUAAAAAN0hnsIFLyzzJ6MWaWb7WaEZ1wKi',
'RECAPTCHA_SECRET_KEY':
'secret-key'})
app=Flask(__name__)
recaptcha = ReCaptcha(app=app)
mail_settings = {
"MAIL_SERVER": 'smtp.gmail.com',
"MAIL_PORT": 465,
"MAIL_USE_SSL": True,
"MAIL_USERNAME": 'USERNAME',
"MAIL_PASSWORD": 'PASSWORD'
}
app.config.update(mail_settings)
mail = Mail(app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/mail', methods=['GET', 'POST'])
def send_mail():
r = requests.post('https://www.google.com/recaptcha/api/siteverify',
data = {'secret' :
'secret_key',
'response' :
request.form['g-recaptcha-response']})
google_response = json.loads(r.text)
print('JSON: ', google_response)
if google_response['success']:
msg = Message('Thank you for contacting me', sender='kristofferlocktolboll#gmail.com', recipients = [request.form['email']])
msg.body ='sut den'
mail.send(msg)
return render_template('index.html')
else:
return render_template('index.html')
app.run(debug=True)
The problem is that whenever I have the flask_recaptcha import ReCaptcha I get the following error:
it looks like the import statement is incorrect, but since I'm not using WTForms, I don't know what do else. Whenever I remove the import statement it gives a syntax error instead (which makes sense)
Usage: flask run [OPTIONS]
Error: The file/path provided (routes) does not appear to exist.
Please verify the path is correct. If app is not on PYTHONPATH,
ensure the extension is .py

API and APP Flask [duplicate]

I'm trying to send a post request to my Flask app from one of its own views, but it hangs until I kill the server. If I do the request in JavaScript, it works fine. Why does it not work from the Python code?
from flask import Blueprint, render_template, abort, request, Response, session, url_for
from jinja2 import TemplateNotFound
from flask.ext.wtf import Form
from wtforms import BooleanField, TextField, PasswordField
import requests
login = Blueprint('login', __name__, template_folder='templates')
class LoginForm(Form):
email = TextField('Email')
password = PasswordField('Password')
#login.route('/login', methods=['GET', 'POST'])
def _login():
form = LoginForm(request.form, csrf_enabled=False)
if form.validate_on_submit():
return requests.post(request.url_root + '/api/login', data={"test": True})
return render_template('login.html', form=form)
Prior to 1.0, Flask's development server was single-threaded by default. In that mode, it can only handle one request at a time. Making a request blocks until it receives the response. Your Flask code makes a request in the one thread, and then waits. There are no other threads to handle this second request. So the request never completes, and the original request waits forever.
Enable threads in the dev server to avoid the deadlock and fix the immediate problem.
app.run(threaded=True)
However, making a full HTTP request to the app from within the app should never be necessary and indicates a deeper design issue. For example, observe that the internal request will not have access to the session on the client's browser. Extract the common code and call it internally, rather than making a new request.
def common_login(data):
...
#app.route("/login")
def login():
...
common_login(data)
...
#app.route("/api/login")
def api_login():
...
common_login(data)
...
I'm not familiar with Flask. However this bit of code:
if form.validate_on_submit():
return requests.post(request.url_root + '/api/login', data={"test": True})
Seems like you're accepting a posted form, validating it, and then posting it again. Over and over.

Route two modules to the same URL in Flask by session

I have a not-logged-in module/blueprint, welcome, and a logged-in blueprint, home. I want a user with a valid session to go to home.index, and a user that is a guest to go to welcome.index. However, I am running into issues because both of those functions route to the same URL, /.
How can I make this functionality possible? I have tried adding:
if(logged_in():
redirect(url_for('home.index'))
to index() in the welcome blueprint, but this of course just causes a circular redirect, because the URL for home.index is the same as welcome.index.
I have also tried to only define welcome.index if logged_in() is true. However, that causes issues because there are other links on the site that link to welcome.index, and if the user is logged in, those cause errors as welcome.index technically no longer exists.
Edit
I am seeing this error AttributeError: 'Blueprint' object has no attribute 'index' from this code:
from flask import Flask, session, g
from modules.welcome import welcome
from modules.home import home as home
from modules.home import index
from modules.welcome import index
app = Flask(__name__)
app.config.from_pyfile('config.cfg')
app.register_blueprint(welcome)
app.register_blueprint(home)
#app.route('/', methods=['GET', 'POST'])
def index():
if 'user_id' in session:
return home.index()
else:
return welcome.index()
Edit #2: Blueprints code
Code in modules/home.py:
from flask import Blueprint, render_template, redirect, url_for, request, session, g
from models.User import User
from helpers.login import *
home = Blueprint('home', __name__)
def index():
return render_template('home/index.html')
Code in modules/welcome.py:
from flask import Blueprint, render_template, redirect, url_for, request, session, g
import md5
from models.User import User
from helpers.login import *
welcome = Blueprint('welcome', __name__)
def index():
alert, email = None, None
if request.method == 'POST' and not logged_in():
email = request.form['email']
password_salt = md5.new(request.form['password']).hexdigest()
user = User.query.filter_by(email=email , password_salt=password_salt).first()
if user is None:
alert = "Wrong username or password!"
else:
session['user_id'] = user.id
return redirect(url_for('home.index'))
return render_template('welcome/index.html', alert=alert, email=email)
#welcome.route('/about')
def about():
return render_template('welcome/about.html')
#welcome.route('/tandp')
def tandp():
return render_template('welcome/tandp.html')
#welcome.route('/logout')
def logout():
session.pop('user_id', None)
return redirect(url_for('welcome.index'))
#welcome.route('/register')
def register():
error = None
return "HI"
Split up your methods, test for logged status and then call the proper function (adding the params you need on each):
from ????? import app
from ????? import logged_in
import home.index
import welcome.index
#app.route('/')
def your_basic_index_view():
if logged_in():
return home.index()
else:
return welcome.index()
Or do the same with a decorator. You won't be able to use a single route pointing conditionally to two different views.
EDIT:
Try the following:
from flask import Flask, session, g
from modules.welcome import welcome
from modules.home import home as home
from modules.home import index as h_index
from modules.welcome import index as w_index
app = Flask(__name__)
app.config.from_pyfile('config.cfg')
app.register_blueprint(welcome)
app.register_blueprint(home)
#app.route('/', methods=['GET', 'POST'])
def index():
if 'user_id' in session:
return h_index()
else:
return w_index()

Categories

Resources