¿Qué es un 'punto final' en Flask?

125

La documentación del Frasco muestra :

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é se entiende exactamente por un "punto final"?

Fuziang
fuente

Respuestas:

267

Cómo funciona el enrutamiento de matraces

La idea completa de Flask (y la biblioteca Werkzeug subyacente) es mapear las rutas URL a alguna lógica que ejecutará (típicamente, la "función de vista"). Su vista básica se define así:

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

Tenga en cuenta que la función a la que se refirió (add_url_rule) logra el mismo objetivo, solo que sin usar la notación de decorador. Por lo tanto, lo siguiente es lo mismo:

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

Supongamos que su sitio web se encuentra en 'www.example.org' y utiliza la vista anterior. El usuario ingresa la siguiente URL en su navegador:

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

El trabajo de Flask es tomar esta URL, descubrir qué quiere hacer el usuario y pasarla a una de sus muchas funciones de Python para su manejo. Toma el camino :

/greeting/Mark

... y lo hace coincidir con la lista de rutas. En nuestro caso, definimos esta ruta para ir a la give_greetingfunción.

Sin embargo, si bien esta es la forma típica en que podría crear una vista, en realidad le extrae información adicional. Detrás de escena, Flask no dio el salto directamente desde la URL a la función de vista que debería manejar esta solicitud. No dice simplemente ...

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

En realidad, hay otro paso, donde asigna la URL a un punto final:

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"

Básicamente, el "punto final" es un identificador que se utiliza para determinar qué unidad lógica de su código debe manejar la solicitud . Normalmente, un punto final es solo el nombre de una función de vista. Sin embargo, en realidad puede cambiar el punto final, como se hace en el siguiente ejemplo.

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

Ahora, cuando Flask dirige la solicitud, la lógica se ve así:

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"

Cómo usa el punto final

El punto final se usa comúnmente para la "búsqueda inversa". Por ejemplo, en una vista de su aplicación Flask, desea hacer referencia a otra vista (tal vez cuando se vincula desde un área del sitio a otra). En lugar de codificar la URL, puede usarla url_for(). Asume lo siguiente

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

Esto es ventajoso, ya que ahora podemos cambiar las URL de nuestra aplicación sin necesidad de cambiar la línea donde hacemos referencia a ese recurso.

¿Por qué no usar siempre el nombre de la función de vista?

Una pregunta que podría surgir es la siguiente: "¿Por qué necesitamos esta capa adicional?" ¿Por qué asignar una ruta a un punto final, luego un punto final a una función de vista? ¿Por qué no simplemente omitir ese paso intermedio?

La razón es porque es más poderoso de esta manera. Por ejemplo, Flask Blueprints le permite dividir su aplicación en varias partes. Es posible que tenga todos mis recursos del lado del administrador en un plan denominado "admin", y todos mis recursos de nivel de usuario en un punto final llamado "usuario".

Los planos le permiten separarlos en espacios de nombres. Por ejemplo...

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

Tenga en cuenta que en ambos planos, la ruta '/ greeting' es una función llamada "saludo". Si quisiera referirme a la función de "saludo" del administrador, no podría simplemente decir "saludo" porque también hay una función de "saludo" del usuario. Los puntos finales permiten una especie de espacio de nombres al hacer que especifique el nombre del plano como parte del punto final. Entonces, podría hacer lo siguiente ...

print url_for('admin.greeting') # Prints '/admin/greeting'
print url_for('user.greeting') # Prints '/user/greeting'
Mark Hildreth
fuente
1
¿Qué tal url_forpara root? Could not build url for endpoint ''
Capté el
Realmente me gustó su explicación, y me dio una buena idea de cómo funcionan estos puntos finales. Sin embargo, ahora que entiendo este concepto, creo que te estás perdiendo un punto relacionado con los puntos finales, específicamente en Flask. Si no especifica los puntos finales, su regla en la url_for()función podría romperse cambiando el nombre de una función / clase por razones X o Y (alguien refactorizó el código y encontró un nombre más apropiado, etc.). Los puntos finales generados automáticamente por Flask lo ayudan a manejar los cambios de url. El punto final explícito le ayuda a lidiar con los cambios de URL y los cambios de nombre de su función.
IMCoins
1
Esto realmente aclara mi comprensión de la funcionalidad del punto final de Flask y tal vez incluso la definición del punto final en general. También encontré algunos errores tipográficos. ¿No debería ser su función Ver en give_greetinglugar de my_greeting? No estoy viendo en my_greetingningún lado ..
#
23

El punto final es el nombre utilizado para realizar una búsqueda inversa de las reglas de URL url_fory el valor predeterminado es el nombre de la función de vista.

Pequeño ejemplo:

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
fuente