368

Is it possible to directly declare a flask URL optional parameter?

Currently I'm proceeding the following way:

@user.route('/<userId>')
@user.route('/<userId>/<username>')
def show(userId, username=None):
    pass

How can I directly say that username is optional?

0

11 Answers 11

502

Another way is to write

@user.route('/<user_id>', defaults={'username': None})
@user.route('/<user_id>/<username>')
def show(user_id, username):
    pass

But I guess that you want to write a single route and mark username as optional? If that's the case, I don't think it's possible.

Sign up to request clarification or add additional context in comments.

10 Comments

Any problems using this method when referencing endpoints and url_for ?
Not that I know of. Even Flask docs contain similar example (you need to scroll down a bit to see it).
You can try pip install flask_optional_routes. I created a pip for the functionality you are requesting b/c I needed it as well. The code is located at: github.com/sudouser2010/flask_optional_routes.
upvoted! if you have multiple tabs on your home page where each one triggers something like /one /two /three /four and you want to load different content on the same page without reloading the page, should you use a single route or multiple routes?
@PirateApp that cannot be achieved with just Flask and is purely a frontend feature
|
248

Almost the same as Audrius cooked up some months ago, but you might find it a bit more readable with the defaults in the function head - the way you are used to with python:

@app.route('/<user_id>')
@app.route('/<user_id>/<username>')
def show(user_id, username='Anonymous'):
    return user_id + ':' + username

3 Comments

Also, the this works if username is not constant. defaults= freezes the default value in a dictionary.
Keep in mind there is a big caveat here: if you have multiple positional arguments and not all of them optional, flask won't understand how to build the URL properly. You can get something like /page?arg=foo where it should be /foo/page . @Audrius Kažukauskas answer works in that case, but this doesn't
This also prevents flask redirecting with 308's when you omit the optional URI path param. ie if you use the defaults= approach with your above default value, and then specify as part of the URI the same Anonymous string as the username optional arg, you will get a 308 bouncing you to /<user_id>
90

If you are using Flask-Restful like me, it is also possible this way:

api.add_resource(UserAPI, '/<userId>', '/<userId>/<username>', endpoint = 'user')

a then in your Resource class:

class UserAPI(Resource):

  def get(self, userId, username=None):
    pass

Comments

37
@user.route('/<userId>/')  # NEED '/' AFTER LINK
@user.route('/<userId>/<username>')
def show(userId, username=None):
    pass

https://flask.palletsprojects.com/en/1.1.x/quickstart/#unique-urls-redirection-behavior

Comments

16
@app.route('/', defaults={'path': ''})
@app.route('/< path:path >')
def catch_all(path):
    return 'You want path: %s' % path

http://flask.pocoo.org/snippets/57/

2 Comments

You should add here the info from the external link because if that link will no longer be valid, your answer will be damaged.
The link is not valid anymore. Lucky us we have archive.org (web.archive.org/web/20190414194437/https://flask.pocoo.org/…)
15
@user.route('/<user_id>', defaults={'username': default_value})
@user.route('/<user_id>/<username>')
def show(user_id, username):
   #
   pass

Comments

8

Almost the same as skornos, but with variable declarations for a more explicit answer. It can work with Flask-RESTful extension:

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class UserAPI(Resource):
    def show(userId, username=None):
    pass

api.add_resource(UserAPI, '/<userId>', '/<userId>/<username>', endpoint='user')

if __name__ == '__main__':
    app.run()

The add_resource method allows pass multiples URLs. Each one will be routed to your Resource.

Comments

5

I know this post is really old but 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)

Comments

0

You can write as you show in example, but than you get build-error.

For fix this:

  1. print app.url_map () in you root .py
  2. you see something like:

<Rule '/<userId>/<username>' (HEAD, POST, OPTIONS, GET) -> user.show_0>

and

<Rule '/<userId>' (HEAD, POST, OPTIONS, GET) -> .show_1>

  1. than in template you can {{ url_for('.show_0', args) }} and {{ url_for('.show_1', args) }}

Comments

-8

Since Flask 0.10 you can`t add multiple routes to one endpoint. But you can add fake endpoint

@user.route('/<userId>')
def show(userId):
   return show_with_username(userId)

@user.route('/<userId>/<username>')
def show_with_username(userId,username=None):
   pass

1 Comment

What? Using flask 0.10.1 here and I can add multiple routes to one endpoint just fine.
-12

I think you can use Blueprint and that's will make ur code look better and neatly.

example:

from flask import Blueprint

bp = Blueprint(__name__, "example")

@bp.route("/example", methods=["POST"])
def example(self):
   print("example")

1 Comment

This does not answer the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.