I am very new to Flask and Web development so sorry in advanced if I use incorrect terms.
I am trying to create a webpage using Python and Flask. To do so, I have the following:
from flask import Flask, request, render_template, redirect, url_for
from flask_assets import Environment, Bundle
app = Flask(__name__)
assets = Environment(app)
#app.route("/", methods=["GET", "POST"])
def login():
# Code to do the login
error = None
if request.method == 'POST':
# code checking the passwords. if correct:
return render_template('index.html')
# else:
# error
return render_template('login.html', error = error)
What this snippet of code does is to load the login.html where the user is asked to put an username and password and after checking if they are the ones expected, it loads index.html where the user can upload his or her data. Once the data is submitted a new function is called:
#app.route('/transform', methods=["POST"])
def transform():
f = request.files['data_file']
if not f:
return "No file"
# code
return render_template('message.html')
The problem is that while in local the message.html gets display once transform has finished, in the server it doesn't appear although the function eventually does what it's expected to do. The other two templates are correctly displayed both in local and in the server. Could it be due to be in a different route?
The index.html is defined with action='\transform', in case it may give a hint.
Any idea of why could this be happening?
Related
I have been coding a flask app that works perfectly fine while running locally, but while hosting the app a strange bug occurs. After I've posted a string to the server it responds with the expected page, but when I repeat it with another request (without restarting the server) the same page as earlier is displayed yet again.
It seems like the render_template does not update the changes I've done in the HTML file after it already has rendered the template, even though the command is run again.
#app.route("/", methods=['POST', 'GET'])
def index():
if request.method == 'POST':
content = str(request.form['content'])
# Some code that changes the "output.html" page based on the user input
return render_template('output.html')
else:
return render_template("index.html")
Why not use redirect instead of render_template in your if condition, like this:
#app.route("/", methods=['POST', 'GET'])
def index():
if request.method == 'POST':
content = str(request.form['content'])
return redirect(url_for('output.html'))
else:
return render_template("index.html")
I found the solution. Apparently the page doesn't update if it has the same URL as before even though a new template is rendered under the same URL. The solution was to make a dynamic URL.
I have started learning flask for web development and experimenting with it since I have a website in mind I would like to create.
My thought has been to create a homepage showing some data that will be updated using cURL or the requests python library. I have some other python code that generates the data to be displayed and I would like to use the POST request for sending a dictionary with the generated information to the server and update the homepage with that new info.
A rather simplistic but comprehensive version of what I have tried so far:
from flask import Flask, redirect, url_for, render_template, request
app = Flask(__name__)
#app.route("/", methods=["POST", "GET"])
def home():
if request.method == "POST":
data = request.form["data"]
return render_template("index.html", content=data)
else:
return render_template("index.html", content="initial_data")
if __name__ == "__main__":
app.run(debug=True)
The code for index.html
<!doctype html>
<html>
<head>
<title>Home Page</title>
</head>
<body>
{{content}}
</body>
</html>
So I would like to send a POST request with some new data to the server and update the webpage with that new data.
import requests
payload = {'data': 'new_data'}
r = requests.post("http://localhost:5000/", data=payload)
All of the above doesn't succeed in updating the data in the webpage when I send a request, it just stays the same. Am I totally off course? Is this even possible in the way I have thought of?
Any comment is much appreciated, thank you.
data is staying the same because it's being reassigned each time as a local variable. When a POST request happens, the variable is created, passed to the template, then destroyed as it goes out of scope.
Try this as an experiment in showing how a variable might persist between page loads, though only until the server restarts:
from flask import Flask, redirect, url_for, render_template, request
app = Flask(__name__)
app_state = {
'data': 'Initial Data'
}
#app.route("/", methods=["POST", "GET"])
def home():
if request.method == "POST":
app_state['data'] = request.form['data']
return render_template("index.html", content=app_state['data'])
if __name__ == "__main__":
app.run(debug=True)
In that example, you're creating a global dictionary, app_date, and updating a key on it every time the user sends a POST request to / with a form payload of data.
Then, we return the template with the content of the dictionary item.
A Few Notes
The implementation I provided would still be vulnerable to race conditions if two people make simultaneous changes.
For this kind of thing, you'll usually want a more persistent solution, like a database.
i am getting "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again." when using blue prints
my app.py code is below,please have a look
__author__ = 'mullapudi'
from flask import Flask,request,redirect,Blueprint,render_template
blueprint = Blueprint('app', __name__, url_prefix='/login')
#blueprint.route('/', methods=['GET', 'POST'])
def admin_login():
# Located at https://yourdomain.com/login
return render_template('admin_login.html')
#blueprint.route('/login/', methods=['GET', 'POST'])
def login():
# Located at https://yourdomain.com/login/login
return render_template('admin_login.html')
my __init__.py code is below
from flask import Flask,request,Blueprint
from app import blueprint
app = Flask(__name__)
app.register_blueprint(blueprint)
app.run()
my html code is below,my form is like this
<form action="{{url_for('app.login')}}" method="post">
now is there any wrong with my code,please help me ,my structure is
/sample ->>project name
/static
/templtes-->>html codes are here
__init__.py
app.py
EDIT
it is working for url localhost:5000/login/
but it is not working for localhost:5000/login/login/
#blueprint.route('/login/', methods=['GET', 'POST'])
def login():
# Located at https://yourdomain.com/login/login
un = request.form['un']
pwd = request.form['pwd']
print un,pwd
if verify_from_database(un,pwd):
print "admin authentication successful"
return render_template('adminPage1.html')
#blueprint.route('/addnew/', methods=['GET', 'POST'])
def adminPage1():
# Located at https://yourdomain.com/login/addnew
return render_template('example.html')
and the form of adminPage1.html is
<form action="{{url_for('app.addnew')}}" method="post">
Your blueprint uses a prefix. You'll need to include this prefix when accessing the routes.
Since you use url_prefix='/login' you need to look for /login/ (for the / route) and /login/login/ (for the /login/ route).
Note that your login() function appears to return None if verify_from_database() returns a false value. You need to always return a valid response from a view (or raise an exception). This is not the cause of your 404 error however.
Suppose i have the following structure:
/root/user/login
I do the login in a blueprint:
app.register_blueprint(login_blueprint,url_prefix=prefix('/user'))
I can redirect to ".index":
#login_blueprint.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
#### this redirects me to '/root/user/'
redirect_to_index= redirect(url_for('.index'))
response = current_app.make_response(redirect_to_index)
# do the log in
return response
redirect_to_index=redirect(url_for('.index'))
response = current_app.make_response(redirect_to_index)
The redirect brings me to /root/user:
redirect(url_for('.index'))
But how to get to /root (which is up relative to the current url (..)?
You can pass url_for the name of the endpoint function for /root/.
For example, if you have:
#app.route('/root/')
def rootindex():
return "this is the index for the whole site."
elsewhere in your app, you can do:
redirect(url_for('rootindex'))
To cause a redirect here. When you put a . in front of the string you pass to url_for, that tells it to look for an endpoint in the current blueprint. By leaving the . off, you tell it to look for a endpoint in the app
I'm writing a web-app using flask, python and HTML. My issue is that the first time I load the a webpage, I get the following error
Bad Request The browser (or proxy) sent a request that this server
could not understand.
I'm able to get the page to load eventually by "tricking" first running it without any flask.request.form calls, and then putting them back in (details below). Something must be going wrong in my initialization. I'm new to flask and using python with HTML.
Assume I'm working from a directory called example. I have a python script called test.py and an HTML template called test.html with the following directory structure:
\example\test.py
\example\templates\test.html
My python script test.py is:
import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"
class View(flask.views.MethodView):
def get(self):
result = flask.request.form['result']
return flask.render_template('test.html', result=result)
# return flask.render_template('test.html')
def post(self):
return self.get()
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()
and my HTML in test.html is
<html>
<head>
</head>
<body>
<form action="/" method="post">
Enter something into the box:
<input type="text" name="result"/><br>
<input type="submit" value="Execute!"/>
</form>
</body>
</html>
Steps to reproduce the error
1: Run the test.py script, and open up the URL in a browser
Running on http://127.0.0.1:5000/
You should see the following error
Bad Request The browser (or proxy) sent a request that this server
could not understand.
2: Comment out the first 2 lines of the def get(self) function and uncomment the 3rd line of the def get(self) function so that test.py looks like this
import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"
class View(flask.views.MethodView):
def get(self):
# result = flask.request.form['result']
# return flask.render_template('test.html', result=result)
return flask.render_template('test.html')
def post(self):
return self.get()
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()
3: Refresh the URL, and you will see that things work (though I ultimately want to be able to return the value of result
4: Now, switch the lines that are commented out again. I.e, uncomment the first 2 lines of the def get(self) function and comment out the 3rd line of the def get(self) function so that test.py looks like this
import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"
class View(flask.views.MethodView):
def get(self):
result = flask.request.form['result']
return flask.render_template('test.html', result=result)
# return flask.render_template('test.html')
def post(self):
return self.get()
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()
5: Refresh the URL and now you see things will be working as desired.
This is just a toy example illustrating the real problem exhibiting this weird behavior of how I have to "trick" my browser into showing me this webpage. The
The issue here is that you are attempting to access POSTed variables in a method that will only handle GET requests. When you attempt to access a query string or POST parameter that is not set Flask will, by default, raise a BadRequest error (because you are asking for something that the person hitting the page did not supply).
What happens if the key does not exist in the form attribute? In that case a special KeyError is raised. You can catch it like a standard KeyError but if you don’t do that, a HTTP 400 Bad Request error page is shown instead. So for many situations you don’t have to deal with that problem.
If you need to access a variable from either request.args (GET) or request.form (POST) and you don't need it to be set use the get method to get the value if it is there (or None if it is not set.
# Will default to None
your_var = request.form.get("some_key")
# Alternately:
your_var = request.form.get("some_key", "alternate_default_value")
Here's an alternate way of structuring your code:
import sys
import flask, flask.views
app = flask.Flask(__name__)
app.secret_key = "bacon"
app.debug = True
class View(flask.views.MethodView):
def get(self):
"""Enable user to provide us with input"""
return self._default_actions()
def post(self):
"""Map user input to our program's inputs - display errors if required"""
result = flask.request.form['result']
# Alternately, if `result` is not *required*
# result = flask.request.form.get("result")
return self._default_actions(result=result)
def _default_actions(self, result=None):
"""Deal with the meat of the matter, taking in whatever params we need
to get or process our information"""
if result is None:
return flask.render_template("test.html")
else:
return flask.render_template("test.html", result=result)
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
if __name__ == "__main__":
app.run()