O que é um 'ponto final' no Flask?


124

A documentação do Flask mostra :

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

O que exatamente se entende por "ponto final"?

Respostas:


267

Como o roteamento do balão funciona

A idéia inteira do Flask (e da biblioteca Werkzeug subjacente) é mapear os caminhos da URL para alguma lógica que você executará (normalmente, a "função de visualização"). Sua visão básica é definida assim:

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

Observe que a função a que você se referiu (add_url_rule) alcança o mesmo objetivo, apenas sem usar a notação do decorador. Portanto, o seguinte é o mesmo:

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

Digamos que seu site esteja localizado em 'www.example.org' e use a visualização acima. O usuário insere o seguinte URL no navegador:

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

O trabalho do Flask é pegar esse URL, descobrir o que o usuário deseja fazer e repassá-lo para uma de suas muitas funções python para manipulação. Leva o caminho :

/greeting/Mark

... e corresponde à lista de rotas. No nosso caso, definimos esse caminho para ir para a give_greetingfunção.

No entanto, embora essa seja a maneira típica de criar uma exibição, ela realmente abstrai algumas informações extras de você. Nos bastidores, o Flask não deu o salto diretamente do URL para a função de exibição que deveria lidar com essa solicitação. Não diz simplesmente ...

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

Na verdade, há outra etapa, onde mapeia a URL para um terminal:

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"

Basicamente, o "ponto final" é um identificador usado para determinar qual unidade lógica do seu código deve lidar com a solicitação . Normalmente, um terminal é apenas o nome de uma função de visualização. No entanto, você pode realmente alterar o terminal, como é feito no exemplo a seguir.

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

Agora, quando o Flask roteia a solicitação, a lógica fica assim:

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"

Como você usa o endpoint

O ponto de extremidade é comumente usado para a "pesquisa inversa". Por exemplo, em uma visualização do seu aplicativo Flask, você deseja fazer referência a outra visualização (talvez quando estiver vinculando de uma área do site para outra). Em vez de codificar o URL, você pode usá-lo url_for(). Suponha o seguinte

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

Isso é vantajoso, pois agora podemos alterar os URLs de nosso aplicativo sem precisar alterar a linha na qual referenciamos esse recurso.

Por que não usar sempre o nome da função view?

Uma pergunta que pode surgir é a seguinte: "Por que precisamos dessa camada extra?" Por que mapear um caminho para um terminal, depois um terminal para uma função de visualização? Por que não pular esse passo do meio?

A razão é porque é mais poderoso dessa maneira. Por exemplo, o Flask Blueprints permite dividir seu aplicativo em várias partes. Talvez eu tenha todos os meus recursos do lado do administrador em um blueprint chamado "admin" e todos os meus recursos no nível do usuário em um nó de extremidade chamado "usuário".

Os modelos permitem separá-los em espaços para nome. Por exemplo...

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

Observe que, nos dois modelos, a rota '/ greeting' é uma função chamada "greeting". Se eu quisesse me referir à função de "saudação" do administrador, não poderia simplesmente dizer "saudação" porque também há uma função de "saudação" do usuário. Os pontos de extremidade permitem um tipo de namespace, especificando o nome do blueprint como parte do ponto de extremidade. Então, eu poderia fazer o seguinte ...

print url_for('admin.greeting') # Prints '/admin/greeting'
print url_for('user.greeting') # Prints '/user/greeting'

1
Como está url_fora raiz? Eu peguei um erroCould not build url for endpoint ''
TomSawyer 19/09/17

Gostei muito da sua explicação e me deu uma boa idéia de como esses pontos de extremidade funcionam. No entanto, agora que entendo esse conceito, acho que você está perdendo um ponto referente aos pontos de extremidade, especificamente no Flask. Se você não especificar os pontos de extremidade, sua regra na url_for()função poderá ser quebrada alterando o nome de uma função / classe por razões X ou Y (alguém refatorou o código e encontrou um nome mais apropriado etc ...). Os pontos de extremidade gerados automaticamente pelo Flask ajudam a lidar com as alterações de URL. O ponto final explícito ajuda a lidar com alterações de URL e alterações de nome de sua função.
IMCoins

1
Isso realmente esclarece minha compreensão da funcionalidade do ponto de extremidade do Flask e talvez até da definição do ponto de extremidade em geral. Também encontrei alguns erros de digitação. Sua função View não deveria ser em give_greetingvez de my_greeting? Eu não estou vendo my_greetingqualquer lugar ..
steveohmn

23

Ponto final é o nome usado para pesquisa inversa das regras de URL url_fore o padrão é o nome da função de exibição.

Pequeno exemplo:

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')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.