I'm trying to add another view to my Flask app. My app/views.py looks like this:
from flask import render_template
from app import app
from helpfulFunctions import *
def getRankingList():
allPlayers = main()
return allPlayers
def displayLimitedNumberOfPlayers(limit):
allPlayers = main()
allPlayers[0] = limitPlayers(allPlayers[0], limit)
allPlayers[1] = limitPlayers(allPlayers[1], limit)
return allPlayers
#app.route("/")
#app.route("/index")
def index():
rankingList = getRankingList()
return render_template('index.html', title='Home', rankingList = rankingList)
#app.route("/top100")
def top100():
rankingList = displayLimitedNumberOfPlayers(100)
return render_template('top100.html', rankingList = rankingList)
if __name__ == '__main__':
app.run(debug=True)
I've tried to mimic how the Miguel Grinberg tutorial defines routes for / and for /index. I've created a view called top100.html in my templates folder, where the "index.html" file also lives. However, when I try to hit localhost:5000/top100.html, I get:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
So it seems like Flask doesn't think that URL has a view associated with it...but I'm not sure why.
Any idea?
Thanks for the help,
bclayman
There is no view top100.html in your code.You can do either of these
localhost:5000/top100
OR
change #app.route("/top100") to #app.route("/top100.html")
The route (or url) is specified in the #app.route() definition, so you should visit localhost:5000/top100.
The render_template top100.html is only referenced internally within Flask to specify the template used. Really, this page could be named anything and does not have to be named in any similar way to the route...it just has to match the template file used to build the page served at that url.
Related
I am running into a problem trying to redirect in Flask using the following:
#views.route('/dash_monitoring/<path:url>')
#login_required
def monitoring_page(url):
return redirect("/home/dash_monitoring/{}".format(url))
The url in <path:url> is in the format https://somesite.com/detail/?id=2102603 but when I try to print it in the function, it prints https://somesite.com/detail only without the id part,so it obviously redirects to /home/dash_monitoring/https://somesite.com/detail instead of /home/dash_monitoring/https://somesite.com/detail/?id=2102603.
What should I do so it keeps the id part and redirects to the right url?
You can use request.url and imply string manipulation:
#views.route('/dash_monitoring/<path:url>')
#login_required
def monitoring_page(url):
parsed_path = request.url.split('/dash_monitoring/')[1]
#return the parsed path
return redirect("/home/dash_monitoring/{}".format(parsed_path))
Alternatively, you can iterate through request.args for creating query string and construct path with args
#views.route('/dash_monitoring/<path:url>')
#login_required
def monitoring_page(url):
query_string = ''
for arg,value in request.args.items():
query_string+=f"{arg}={value}&"
query_string=query_string[:-1] # to remove & at the end
path=f"{path}?{query_string}"
#return the parsed path
return redirect(f"/home/dash_monitoring/{path}")
I hope this helps :)
This has an easy solution, we use the url_for function:
from flask import Flask, redirect, url_for
app = Flask(__name__)
#app.route('/<name>')
def index(name):
return f"Hello {name}!"
#app.route('/admin')
def admin():
return redirect(url_for('index',name = 'John'))
if __name__ == '__main__':
app.run(debug = True)
In my code we firs import redirect and url_for.
We create 2 routes index and admin.
In index route we output a simple response with the named passed to the url. So if we get example.com/John it will output Hello John!.
In admin route we redirect the user to index route because it's not the admin (This is a simple example that can you can model with what you want). The index route needs a name so we pass inside the url_for function some context so it can desplay the name.
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?
I want to define multiple endpoints that render different templates, without writing out each one. The endpoints are all similar, one looks like:
#app.route('/dashboard/')
def dashboard():
return render_template('endpoints/dashboard.html')
I tried defining a function in a for loop for each endpoint name, but the problem is that the name of the function stays the same and Flask raises an error about that.
routes = ['dashboard', 'messages', 'profile', 'misc']
for route in routes:
#app.route('/' + route + '/')
def route():
return render_template('endpoints/' + route + '.html')
How can I create these views without repeating myself?
You don't want to do this. Instead, use a variable in the route to capture the template name, try to render the template, and return a 404 error if the template doesn't exist.
from flask import render_template, abort
from jinja2 import TemplateNotFound
#app.route('/<page>/')
def render_page(page):
try:
return render_template('endpoints/{}.html'.format(page))
except TemplateNotFound:
abort(404)
Alternatively, and less preferably, you can use the same function name as long as you provide Flask with unique endpoint names. The default name is the name of the function, which is why Flask complains.
for name in routes:
#app.route('/', endpoint=name)
def page():
return render_template('endpoints/{}.html'.format(name))
I have some problem with redirecting with anchors from python code.
My code:
func():
...
redirect(url_for('my_view', param=param, _anchor='my_anchor'))
This redirect didn't redirect me to #my_anchor.
In template link like:
works good... May be problem in flask function "redirect".
How I can use redirect with anchors in Flask?
Flask version 0.10.x
if your goal is to be redirected to a page with an anchor preselected in the url I think the problem may be connected to the function you have passed in the 'url_for'. Below is my attempt to do what you described.
views.py
from flask import Flask
from flask import redirect, url_for
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route('/myredirect')
def my_redirect():
return redirect(url_for('hello_world',_anchor='my_anchor'))
if __name__ == '__main__':
app.run()
This does not need a template, as as soon as you hit /myredirect you are redirected to / with anchor #my_anchor
After you get your views started with $ python views.py and navigate to http://127.0.0.1:5000/myredirect you end up on http://127.0.0.1:5000/#my_anchor
A short and simple way of doing this is
return redirect(url_for('hello_world') + '#my_anchor')
instead of
return redirect(url_for('hello_world',_anchor='my_anchor'))
which works because url_for returns a string for the endpoint.
I've been trying to understand how to generate dynamic Flask URLs. I've read the docs and several example, but can't figure out why this code doesn't work:
path = 'foo'
#app.route('/<path:path>', methods=['POST'])
def index(path=None):
# do some stuff...
return flask.render_template('index.html', path=path)
I'd expect my index.html template to be served to /foo, but it is not. I get a build error. What am I missing?
If I use a fixed path, like /bar, everything works without issue.
#app.route('/bar', methods=['POST'])
You've got the long and short of it already. All you need to do is decorate your view functions using the /<var> syntax (or the /<converter:var> syntax where appropriate).
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/<word>', defaults={'word': 'bird'})
def word_up(word):
return render_template('whatstheword.html', word=word)
#app.route('/files/<path:path>')
def serve_file(path):
return send_from_directory(app.config['UPLOAD_DIR'], path, as_attachment=True)
if __name__ == '__main__':
app.debug = True
app.run(port=9017)
When Flask pulls a variable out of a URL for a dynamic route like you're trying to use, it'll be a unicode string in Python by default. If you create the variable with the <int:var> or <float:var> converters, it'll be converted to the appropriate type in the app space for you.
The <path:blah> converter will match on a string that contains slashes (/), so you can pass /blah/dee/blah and the path variable in your view function will contain that string. Without using the path converter, flask would try and dispatch your request to a view function registered on the route /blah/dee/blah, because the plain <var> is delineated by the next / in the uri.
So looking at my little app, the /files/<path:path> route would serve whatever file it could find that matched the path sent up by the user on the request. I pulled this example from the docs here.
Also, dig that you can specify defaults for your variable URLs via a keyword arg to the route() decorator.
If you want, you can even access the underlying url_map that Werkzeug builds based on how you specify your view functions and routes in your app space. For more stuff to chew on, check out the api docs on URL registrations.
You can use add_url_rule():
def index(path=None):
return render_template('index.html', path=path)
path = '/foo'
app.add_url_rule(path, 'index', index)
You also might want to look at blueprint objects if you end up doing this alot.