Flask peut-il avoir des paramètres d'URL facultatifs?


258

Est-il possible de déclarer directement un paramètre facultatif d'URL de flacon?

Actuellement, je procède de la manière suivante:

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

Comment puis-je dire directement que usernamec'est facultatif?

Réponses:


341

Une autre façon est d'écrire

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

Mais je suppose que vous voulez écrire un seul itinéraire et le marquer usernamecomme facultatif? Si c'est le cas, je ne pense pas que ce soit possible.


Des problèmes avec cette méthode lors du référencement des points de terminaison et url_for?

2
Pas que je sache de. Même les documents Flask contiennent un exemple similaire (vous devez faire défiler un peu pour le voir).
Audrius Kažukauskas

1
Vous pouvez essayer pip install flask_optional_routes. J'ai créé un pip pour la fonctionnalité que vous demandez, car j'en avais également besoin. Le code se trouve sur: github.com/sudouser2010/flask_optional_routes .
sudouser2010

voté! si vous avez plusieurs onglets sur votre page d'accueil où chacun déclenche quelque chose comme / un / deux / trois / quatre et que vous souhaitez charger un contenu différent sur la même page sans recharger la page, devez-vous utiliser un seul itinéraire ou plusieurs itinéraires?
PirateApp

@PirateApp qui ne peut pas être réalisé avec seulement Flask et est purement une fonctionnalité
frontale

183

Presque la même chose qu'Audrius a préparé il y a quelques mois, mais vous pourriez le trouver un peu plus lisible avec les valeurs par défaut dans la tête de fonction - la façon dont vous êtes habitué avec python:

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

3
En outre, cela fonctionne si usernamen'est pas constant. defaults=fige la valeur par défaut dans un dictionnaire.
kasperhj

2
Je préfère celui-ci. Nous devons garder le code aussi propre que possible.
Light.G

Gardez à l'esprit qu'il y a une grande mise en garde ici: si vous avez plusieurs arguments positionnels et pas tous optionnels, flask ne comprendra pas comment construire l'URL correctement. Vous pouvez obtenir quelque chose comme / page? Arg = foo où il devrait être / foo / page. @Audrius Kažukauskas réponse fonctionne dans ce cas, mais ce n'est pas le cas
rgargente

73

Si vous utilisez Flask-Restful comme moi, il est également possible de cette façon:

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

puis dans votre classe Ressource:

class UserAPI(Resource):

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


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

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


3
Vous devez ajouter ici les informations du lien externe car si ce lien n'est plus valide, votre réponse sera endommagée.
tomab

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

5

Presque le même que skornos, mais avec des déclarations de variables pour une réponse plus explicite. Il peut fonctionner avec l' extension Flask-RESTful :

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()

La add_resourceméthode permet de transmettre plusieurs URL. Chacun sera acheminé vers votre ressource .


1

Je sais que ce post est vraiment ancien mais j'ai travaillé sur un package qui fait cela appelé flask_optional_routes. Le code est situé sur: 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)

0

Vous pouvez écrire comme vous le montrez dans l'exemple, mais vous obtenez une erreur de build.

Pour résoudre ce problème:

  1. imprimer app.url_map () dans votre racine .py
  2. vous voyez quelque chose comme:

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

et

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

  1. que dans le modèle que vous pouvez {{ url_for('.show_0', args) }}et{{ url_for('.show_1', args) }}

-6

Depuis Flask 0.10, vous ne pouvez pas ajouter plusieurs routes à un point de terminaison. Mais vous pouvez ajouter un faux point de terminaison

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

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

5
Quoi? En utilisant le flacon 0.10.1 ici et je peux ajouter plusieurs routes à un point de terminaison très bien.
jaapz

-8

Je pense que vous pouvez utiliser Blueprint et cela rendra votre code plus beau et plus net.

exemple:

from flask import Blueprint

bp = Blueprint(__name__, "example")

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

Cela ne répond pas à la question.
meyer9
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.