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.
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.
On Successfully POSTing to a form endpoint I redirect back to the same endpoint with some URL params that my client side code can interact with.
#bp.route('/submit', methods=['GET', 'POST'])
def submit():
form = SubmissionForm()
labels = current_app.config['TRELLO_LABELS']
if form.validate_on_submit():
submission = Submission().create(
title=form.data['title'], email=form.data['email'], card_id=card.id, card_url=card.url)
# reset form by redirecting back and setting the URL params
return redirect(url_for('bp.submit', success=1, id=card.id))
return render_template('submit.html', form=form)
But I ran into some issues trying to write a test for this code as I can't figure out how to test that those URL params are on my redirect URL. My incomplete test code is:
import pytest
#pytest.mark.usefixtures('session')
class TestRoutes:
def test_submit_post(self, app, mocker):
with app.test_request_context('/submit',
method='post',
query_string=dict(
email='email#example.com',
title='foo',
pitch='foo',
format='IN-DEPTH',
audience='INTERMEDIATE',
description='foo',
notes='foo')):
assert resp.status_code == 200
I've tried a few different methods to test this. With and without the context manager and I've dug deep into the Flask and Werkzeug source on the test_client and test_request_context.
I just want to test that the URL params for success and id exist on redirect after a valid POST.
Here's a super simple yet inclusive example of patching Flask's url_for method (can be run as-is in a Python interpreter):
import flask
from unittest.mock import patch
#patch('flask.url_for')
def test(self):
resp = flask.url_for('spam')
self.assert_called_with('spam')
However, the above example will only work if you're importing Flask directly and not using from flask import url_for in your routes code. You'll have to patch the exact namespace, which would look something like this:
#patch('application.routes.url_for')
def another_test(self, client):
# Some code that envokes Flask's url_for, such as:
client.post('/submit', data={}, follow_redirects=True)
self.assert_called_once_with('bp.submit', success=1, id=1)
For more info, check out Where to Patch in the mock documentation.
You could use mock's function patch function to patch url_for capturing the provided arguments and then test against them.
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 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