Reputation: 43
I have a Route named search: @app.route('/search') Is it possible to add multiple optional parameters to it? Example:
@app.route('/search/pg/<int:pg>')
@app.route('/search/types/<types>')
@app.route('/search/number/<int:number>')
@app.route('/search/subject/<subject>')
The order in the URL shouldnt matter, so I could call /search/pg/2, or /search/subject/MySubject/pg/2 or /search/types/posts/subject/MySubject/pg/2
I tried this, but it only works with the full paths and all the parameters:
@app.route('/search/pg/<int:pg>/types/<types>/subject/<subject>', methods=['GET', 'POST'])
@app.route('/search/subject', defaults={'subject', None})
@app.route('/search/pg/<int:pg>/types/<types>', methods=['GET', 'POST'])
@app.route('/search/types', defaults={'types', None})
@app.route('/search', defaults={'pg': 1}, methods=['GET', 'POST'])
@app.route('/search/pg/<int:pg>', methods=['GET', 'POST'])
def search(pg, types=None, subject=None):
pass
Upvotes: 4
Views: 16472
Reputation: 1062
If you are trying to route a user based on multiple, optional form values as route parameters, then I found a useful workaround.
First, create an intermediate route that will create the query string. This route will only allow for POST methods (since the 1 or more of the form values would be submitted by the form).
@app.route('/example', methods=['POST']
def createQueryParams():
form = ExampleForm()
# Retrieve/cleanse/validate form data
example1 = form.example_field1.data
example2 = form.example_field2.data
return redirect(url_for('app.route', example1=example1, example2=example2))
Note that each keyword argument in the redirect(url_for())
needs to either be a parameter used in app.route or something you expect to add as a query parameter.
Next, alter your app.route() to have a GET method and extract the query parameters like @lee-pai-long mentioned
@app.route('/search', methods=['GET'])
def search():
if len(request.args) > 0:
example1 = request.args.get('example1')
example2 = request.args.get('example2')
# Do stuff
Finally, in the .html template where the form is submitted, make sure the form action directs to the createQueryParams
route, not the search
route. Such as
<form action="{{ url_for('app.createQueryParams') }}" method="POST">
<!-- Flask form stuff -->
</form>
I used this structure to create a page where users could filter posts based on up to X different criteria (title search, date sort, tags, etc.). I wanted to be able to have an optimized query parameter, but without the intermediary createQueryParams
route, I was not able to determine what form values were selected until after the url was created, since the single route owned both methods.
Upvotes: 2
Reputation: 171
@David, I worked on a package that does this called flask_optional_routes. The code is located at: https://github.com/sudouser2010/flask_optional_routes.
from flask import Flask
from flask_optional_routes import OptionalRoutes
app = Flask(__name__)
optional = OptionalRoutes(app)
@optional.routes('/<user_id>/<user_name>?/')
def foobar(user_id, user_name=None):
return 'it worked!'
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
Upvotes: 2
Reputation: 2292
You can use filter in the URL instead of "sub-resources".
Then you can put search arguments in any order in your request:
/search?pg=<pg>&types=<types>
Inside the flask view function you can retrieve parameters from the request object:
@app.route('/search/')
def search():
pg = request.args.get('pg')
...
Upvotes: 11