I want to know what the best way is to serve up a redirect in Flask. I have a delete button which looks like this:
<button class="btn btn-danger btn-mini" type="button">Delete</button>
Which calls this app.route:
#app.route('/elastic_ips/<region>/delete/<ip>')
def delete_elastic_ip(region=None,ip=None):
creds = config.get_ec2_conf()
conn = connect_to_region(region, aws_access_key_id=creds['AWS_ACCESS_KEY_ID'], aws_secret_access_key=creds['AWS_SECRET_ACCESS_KEY'])
ip = ip.encode('ascii')
elis = conn.get_all_addresses(addresses=ip)
for eli in elis:
result = []
r = eli.release()
result.append(r)
return Response(json.dumps(result), mimetype='application/json')
I rather not return the result as json. I'm not sure what the "proper" way to return to the page with the delete button. Either I can put in an HTML page that just does a redirect to the refer, or is there a built in way in Flask to have return be an app.route?
Well if you want to return the url of the delete_elastic_ip, it is easy to do with url_for function (more about this function)
Don't know if this endpoint is in some blueprint, but if not, this is simple as that:
from flask import url_for, redirect
.... your code ...
return url_for('delete_elastic_ip', region=None, ip=None)
You can replace Nones also with the values you need of course :) And this will return you the url to the endpoint. Btw this is also a way to go with the urls in templates. Do not hardcode them, use url_for function in jinja templates to generate urls to the views for you. The function is available as a standart global variable in templates (more)
Also if you want just to redirect directly to some other endpoint and do not return anything, there is a function redirect in flask. Use it combined with url_for and you are good to go ;)
from flask import url_for, redirect
... your code...
return redirect(url_for('delete_elastic_ip', region=None, ip=None))
It will refresh the page, so not the best way for ajax redirect though if you want that. For ajax, just return json with the url_for result and do the stuff with it.
Here is another method using render_template
app.py code
from flask import Flask, request,render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/v_timestamp')
def v_timestamp():
return render_template('v_timestamp.html')
then can redirect to v_timestamp page. If you want this to be done via a button click event. Inside template folder, in your v_timestamp.html have this bit of code
<p align="center">v timestamp</button></p>
define button element and an a href inside the same paragraph element, in my case a href v_timestamp means v_timetsamp.html write the respective .html page you want to redirect towards.
File structure
-app.py
-templates
index.html
v_timestamp.html
Related
I'd like to route multiple pages to the sample template, with a parameter, and let the other static files to be automatically routed as well:
#route('/test1')
#route('/hello2')
#route('/page3')
#view('tpl/page.html')
def page():
context = {'request': request, 'pagename': ??}
return (context)
#route('/<filename>')
def files(filename):
return static_file(filename, root='./static/')
and I'd like page.html to display the request name:
<div>This is the page that was requested: {{pagename}} </div>
I expect here:
This is the page that was requested: hello2
How to direct multiple pages to the same template, and have access to the pagename?
I tried str(request).split('example.com/')[1].replace('>', '') but this is a dirty hack, I imagine there's a cleaner way to get test1, hello2, etc. from a #route.
You can do it like this:
#route('/test1', route_name='test1')
#route('/hello2', route_name='hello2')
#route('/page3', route_name='page3')
#view('tpl/page.html')
def page(route_name):
context = {'request': request, 'pagename': route_name}
return (context)
Flask automatically passes unmatched arguments to your route.
I have a view that is accessed by clicking a link on the index page. The view will perform an action and should then show the index page again. My view does that, but the url is still the url of the action view, not the index view. How can I redirect back to the index view?
#app.route('/')
def index():
return render_template('index.html')
#app.route('/u1/')
def u1():
# do something
return render_template('index.html')
Use url_for to build a url to another endpoint in the app. Use redirect to create a redirect response with that url.
from flask import url_for, redirect
#app.route('/u1/')
def u1():
# do something
return redirect(url_for('index'))
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.
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.
The Flask documentation shows:
add_url_rule(*args, **kwargs)
Connects a URL rule. Works exactly like the route() decorator.
If a view_func is provided it will be registered with the endpoint.
endpoint – the endpoint for the registered URL rule. Flask itself assumes the name of the view function as endpoint
What exactly is meant by an "endpoint"?
How Flask Routing Works
The entire idea of Flask (and the underlying Werkzeug library) is to map URL paths to some logic that you will run (typically, the "view function"). Your basic view is defined like this:
#app.route('/greeting/<name>')
def give_greeting(name):
return 'Hello, {0}!'.format(name)
Note that the function you referred to (add_url_rule) achieves the same goal, just without using the decorator notation. Therefore, the following is the same:
# No "route" decorator here. We will add routing using a different method below.
def give_greeting(name):
return 'Hello, {0}!'.format(name)
app.add_url_rule('/greeting/<name>', 'give_greeting', give_greeting)
Let's say your website is located at 'www.example.org' and uses the above view. The user enters the following URL into their browser:
http://www.example.org/greeting/Mark
The job of Flask is to take this URL, figure out what the user wants to do, and pass it on to one of your many python functions for handling. It takes the path:
/greeting/Mark
...and matches it to the list of routes. In our case, we defined this path to go to the give_greeting function.
However, while this is the typical way that you might go about creating a view, it actually abstracts some extra info from you. Behind the scenes, Flask did not make the leap directly from URL to the view function that should handle this request. It does not simply say...
URL (http://www.example.org/greeting/Mark) should be handled by View Function (the function "give_greeting")
Actually, it there is another step, where it maps the URL to an endpoint:
URL (http://www.example.org/greeting/Mark) should be handled by Endpoint "give_greeting".
Requests to Endpoint "give_greeting" should be handled by View Function "give_greeting"
Basically, the "endpoint" is an identifier that is used in determining what logical unit of your code should handle the request. Normally, an endpoint is just the name of a view function. However, you can actually change the endpoint, as is done in the following example.
#app.route('/greeting/<name>', endpoint='say_hello')
def give_greeting(name):
return 'Hello, {0}!'.format(name)
Now, when Flask routes the request, the logic looks like this:
URL (http://www.example.org/greeting/Mark) should be handled by Endpoint "say_hello".
Endpoint "say_hello" should be handled by View Function "give_greeting"
How You Use the Endpoint
The endpoint is commonly used for the "reverse lookup". For example, in one view of your Flask application, you want to reference another view (perhaps when you are linking from one area of the site to another). Rather than hard-code the URL, you can use url_for(). Assume the following
#app.route('/')
def index():
print url_for('give_greeting', name='Mark') # This will print '/greeting/Mark'
#app.route('/greeting/<name>')
def give_greeting(name):
return 'Hello, {0}!'.format(name)
This is advantageous, as now we can change the URLs of our application without needing to change the line where we reference that resource.
Why not just always use the name of the view function?
One question that might come up is the following: "Why do we need this extra layer?" Why map a path to an endpoint, then an endpoint to a view function? Why not just skip that middle step?
The reason is because it is more powerful this way. For example, Flask Blueprints allow you to split your application into various parts. I might have all of my admin-side resources in a blueprint called "admin", and all of my user-level resources in an endpoint called "user".
Blueprints allow you to separate these into namespaces. For example...
main.py:
from flask import Flask, Blueprint
from admin import admin
from user import user
app = Flask(__name__)
app.register_blueprint(admin, url_prefix='admin')
app.register_blueprint(user, url_prefix='user')
admin.py:
admin = Blueprint('admin', __name__)
#admin.route('/greeting')
def greeting():
return 'Hello, administrative user!'
user.py:
user = Blueprint('user', __name__)
#user.route('/greeting')
def greeting():
return 'Hello, lowly normal user!'
Note that in both blueprints, the '/greeting' route is a function called "greeting". If I wanted to refer to the admin "greeting" function, I couldn't just say "greeting" because there is also a user "greeting" function. Endpoints allow for a sort of namespacing by having you specify the name of the blueprint as part of the endpoint. So, I could do the following...
print url_for('admin.greeting') # Prints '/admin/greeting'
print url_for('user.greeting') # Prints '/user/greeting'
Endpoint is the name used to reverse-lookup the url rules with url_for and it defaults to the name of the view function.
Small example:
from flask import Flask, url_for
app = Flask(__name__)
# We can use url_for('foo_view') for reverse-lookups in templates or view functions
#app.route('/foo')
def foo_view():
pass
# We now specify the custom endpoint named 'bufar'. url_for('bar_view') will fail!
#app.route('/bar', endpoint='bufar')
def bar_view():
pass
with app.test_request_context('/'):
print url_for('foo_view')
print url_for('bufar')
# url_for('bar_view') will raise werkzeug.routing.BuildError
print url_for('bar_view')
If you have same class name and want to map with multiple routes, then specify the endpoint, so that framework will differentiate between two:
class ClassName(Resource):
def get(self):
if request.endpoint!='hello':
return {"data": "Hello"}
elif:
return {"data" : "World"}
api.add_resource(ClassName, '/rout1', endpoint = "world")
api.add_resource(ClassName, '/rout2', endpoint="hello")
#app.route('/') #Endpoint
def a_function(): #View function
return 'view'
Inside Flask, every endpoint with its request methods mapped to a view function. When you use app.route decorator you are actually adding a URL rule.