Qu'est-ce qu'un «point final» dans Flask?

125

La documentation Flask montre :

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

Qu'entend-on exactement par «point final»?

Fuziang
la source

Réponses:

267

Fonctionnement du routage Flask

L'idée entière de Flask (et de la bibliothèque Werkzeug sous-jacente) est de mapper les chemins d'URL vers une logique que vous exécuterez (généralement, la «fonction d'affichage»). Votre vue de base est définie comme ceci:

@app.route('/greeting/<name>')
def give_greeting(name):
    return 'Hello, {0}!'.format(name)

Notez que la fonction à laquelle vous faites référence (add_url_rule) atteint le même objectif, juste sans utiliser la notation décoratrice. Par conséquent, ce qui suit est le même:

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

Supposons que votre site Web se trouve à «www.example.org» et utilise la vue ci-dessus. L'utilisateur entre l'URL suivante dans son navigateur:

http://www.example.org/greeting/Mark

Le travail de Flask est de prendre cette URL, de déterminer ce que l'utilisateur veut faire et de la transmettre à l'une de vos nombreuses fonctions python pour la gestion. Il prend le chemin :

/greeting/Mark

... et le fait correspondre à la liste des itinéraires. Dans notre cas, nous avons défini ce chemin pour accéder à la give_greetingfonction.

Cependant, bien que ce soit la manière typique dont vous pouvez créer une vue, cela extrait en fait des informations supplémentaires de votre part. Dans les coulisses, Flask n'a pas fait le saut directement de l'URL à la fonction d'affichage qui devrait gérer cette demande. Il ne dit pas simplement ...

URL (http://www.example.org/greeting/Mark) should be handled by View Function (the function "give_greeting")

En fait, il y a une autre étape, où il mappe l'URL à un point de terminaison:

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"

Fondamentalement, le «point de terminaison» est un identifiant utilisé pour déterminer quelle unité logique de votre code doit gérer la demande . Normalement, un point de terminaison est simplement le nom d'une fonction de vue. Cependant, vous pouvez réellement modifier le point de terminaison, comme cela est fait dans l'exemple suivant.

@app.route('/greeting/<name>', endpoint='say_hello')
def give_greeting(name):
    return 'Hello, {0}!'.format(name)

Maintenant, lorsque Flask achemine la demande, la logique ressemble à ceci:

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"

Comment vous utilisez le point de terminaison

Le point de terminaison est couramment utilisé pour la "recherche inversée". Par exemple, dans une vue de votre application Flask, vous souhaitez référencer une autre vue (peut-être lorsque vous créez un lien d'une zone du site à une autre). Plutôt que de coder l'URL en dur, vous pouvez utiliser url_for(). Supposons ce qui suit

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

Ceci est avantageux, car maintenant nous pouvons changer les URL de notre application sans avoir besoin de changer la ligne où nous référencons cette ressource.

Pourquoi ne pas toujours utiliser le nom de la fonction d'affichage?

Une question qui pourrait se poser est la suivante: "Pourquoi avons-nous besoin de cette couche supplémentaire?" Pourquoi mapper un chemin vers un point final, puis un point final vers une fonction de vue? Pourquoi ne pas simplement sauter cette étape intermédiaire?

La raison en est qu'il est plus puissant de cette façon. Par exemple, Flask Blueprints vous permet de diviser votre application en plusieurs parties. Je pourrais avoir toutes mes ressources côté administrateur dans un plan appelé «admin», et toutes mes ressources au niveau utilisateur dans un point final appelé «utilisateur».

Les Blueprints vous permettent de les séparer en espaces de noms. Par exemple...

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!'

Notez que dans les deux plans, la route '/ salutation' est une fonction appelée "salutation". Si je voulais faire référence à la fonction "salutation" de l'administrateur, je ne pourrais pas simplement dire "salutation" car il existe également une fonction "salutation" utilisateur. Les points de terminaison permettent une sorte d'espacement de noms en vous demandant de spécifier le nom du plan dans le cadre du point de terminaison. Donc, je pourrais faire ce qui suit ...

print url_for('admin.greeting') # Prints '/admin/greeting'
print url_for('user.greeting') # Prints '/user/greeting'
Mark Hildreth
la source
1
Comment url_forpour root? J'ai attrapé une erreurCould not build url for endpoint ''
TomSawyer
J'ai beaucoup aimé votre explication et cela m'a donné une bonne idée du fonctionnement de ces points de terminaison. Cependant, maintenant que je comprends ce concept, je pense que vous manquez un point concernant les points de terminaison, dans Flask en particulier. Si vous ne spécifiez pas les points de terminaison, votre règle dans la url_for()fonction pourrait être brisée en changeant le nom d'une fonction / classe pour des raisons X ou Y (quelqu'un a refactoré le code et a trouvé un nom plus approprié, etc.). Les points de terminaison générés automatiquement par Flask vous aident à gérer les modifications d'url. Le point de terminaison explicite vous aide à gérer les changements d'url et les changements de nom de votre func.
IMCoins
1
Cela clarifie vraiment ma compréhension de la fonctionnalité de point final de Flask et peut-être même de la définition du point final en général. J'ai aussi trouvé une faute de frappe. Votre fonction View ne devrait-elle pas être à la give_greetingplace de my_greeting? Je ne vois my_greetingnulle part ..
steveohmn
23

Endpoint est le nom utilisé pour inverser la recherche des règles d'URL avec url_foret il est par défaut le nom de la fonction d'affichage.

Petit exemple:

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')
plaes
la source