Etapa 2: Criar um aplicativo Flask com exibições e modelos de página

Etapa anterior: Criar uma solução e um projeto do Visual Studio

Na etapa 1 deste tutorial, você criou um aplicativo Flask com uma página e todo o código em um único arquivo. Para permitir o desenvolvimento futuro, é melhor refatorar o código e criar uma estrutura para modelos de página. Em particular, separe o código para exibições do aplicativo de outros aspectos como o código de inicialização.

Nesta etapa, você aprenderá a:

  • Refatorar o código do aplicativo para separar exibições do código de inicialização (etapa 2-1)
  • Renderizar uma exibição usando um modelo de página (etapa 2-2)

Etapa 2-1: Refatorar o projeto para dar suporte ao desenvolvimento adicional

No código criado pelo modelo "Projeto Web em Branco do Flask", você tem um único arquivo app.py que contém o código de inicialização junto com uma única exibição. Para permitir o desenvolvimento adicional de um aplicativo com várias exibições e modelos, é melhor separar essas preocupações.

  1. Na pasta do seu projeto, crie uma pasta de aplicativo chamada HelloFlask (clique com o botão direito do mouse no projeto em Gerenciador de Soluções e selecione Adicionar>Nova Pasta.)

  2. Na pasta HelloFlask, crie um arquivo chamado __init__.py com o seguinte conteúdo que cria a instância Flask e carrega as exibições do aplicativo (criadas na próxima etapa):

    from flask import Flask
    app = Flask(__name__)
    
    import HelloFlask.views
    
  3. Na pasta HelloFlask, crie um arquivo chamado views.py com o conteúdo a seguir. O nome views.py é importante, porque você usou import HelloFlask.views dentro de __init__.py; você verá um erro em tempo de execução se os nomes não corresponderem.

    from flask import Flask
    from HelloFlask import app
    
    @app.route('/')
    @app.route('/home')
    def home():
        return "Hello Flask!"
    

    Além de renomear a função e a rota como home, esse código contém o código de renderização da página de app.py e importa o objeto app declarado em __init__.py.

  4. Crie uma subpasta em HelloFlask chamada templates, que permanecerá vazia por enquanto.

  5. Na pasta raiz do projeto, renomeie app.py como runserver.py e faça o conteúdo corresponder ao seguinte código:

    import os
    from HelloFlask import app    # Imports the code from HelloFlask/__init__.py
    
    if __name__ == '__main__':
        HOST = os.environ.get('SERVER_HOST', 'localhost')
    
        try:
            PORT = int(os.environ.get('SERVER_PORT', '5555'))
        except ValueError:
            PORT = 5555
    
        app.run(HOST, PORT)
    
  6. A estrutura do seu projeto deve ser semelhante à da imagem a seguir:

    Project structure after refactoring the code

  7. Selecione Depurar>Iniciar Depuração (F5) ou use o botão Servidor Web na barra de ferramentas (o navegador exibido poderá variar) para iniciar o aplicativo e abrir um navegador. Experimente as rotas de URL / e /home.

  8. Também é possível definir pontos de interrupção em várias partes do código e reiniciar o aplicativo para seguir a sequência de inicialização. Por exemplo, defina um ponto de interrupção nas primeiras linhas de runserver.py e HelloFlask_*init_.py e na linha return "Hello Flask!" de views.py. Em seguida, reinicie o aplicativo (Depurar>Reiniciar, Ctrl+Shift+F5 ou o botão de barra de ferramentas mostrado abaixo) e execute o código em etapas (F10) ou execute-o em cada ponto de interrupção usando F5.

    Restart button on the debugging toolbar in Visual Studio

  9. Interrompa o aplicativo ao terminar.

Confirmar o controle do código-fonte

Depois de fazer as alterações no código e testar com êxito, você pode examinar e confirmar as alterações no controle do código-fonte. Em etapas posteriores, quando este tutorial lembrar você de fazer commit com o controle do código-fonte novamente, consulte esta seção.

  1. Selecione o botão de alterações na parte inferior do Visual Studio (circulado abaixo), que encaminha para o Team Explorer.

    Source control changes button on the Visual Studio status bar

  2. No Team Explorer, digite uma mensagem de confirmação como "Refatorar código" e selecione Confirmar Tudo. Quando a confirmação for concluída, você verá uma mensagem Commit <hash> criada localmente. Sincronize para compartilhar suas alterações com o servidor. Se você quiser enviar alterações por push para o repositório remoto, selecione Sincronizar e, em seguida, selecione efetuar push em Commits de saída. Também é possível acumular várias confirmações locais antes de enviar para o repositório remoto.

    Push commits to remote in Team Explorer

Pergunta: Com que frequência é necessário fazer a confirmação no controle do código-fonte?

Resposta: A confirmação de alterações no controle do código-fonte cria um registro no log de alterações e um ponto em que é possível reverter o repositório, se necessário. Cada confirmação também pode ser examinada para suas alterações específicas. Como as confirmações no GIT não são caras, é melhor realizar confirmações frequentes do que acumular um grande número de alterações em uma única confirmação. Não é necessário confirmar cada pequena alteração em arquivos individuais. Normalmente, você realiza uma confirmação ao adicionar uma funcionalidade, alterando uma estrutura como você fez nesta etapa, ou refatorar algum código. Verifique também com outras pessoas da sua equipe para a granularidade de confirmações que funcionam melhor para todos.

A frequência de confirmação e a frequência de envio de confirmações por push a um repositório remoto são duas preocupações diferentes. Você pode acumular várias confirmações no seu repositório local antes de enviá-las por push para o repositório remoto. A frequência dos commits depende de como sua equipe deseja gerenciar o repositório.

Etapa 2-2: Usar um modelo para renderizar uma página

A função home que você tem até agora em views.py não gera nada além de uma resposta HTTP de texto sem formatação para a página. No entanto, a maioria das páginas da Web reais respondem com páginas HTML avançadas que incorporam dados dinâmicos com frequência. A principal razão para definir uma exibição usando uma função é gerar esse conteúdo dinamicamente.

Como o valor retornado para a exibição é apenas uma cadeia de caracteres, é possível criar qualquer HTML que desejar dentro de uma cadeia de caracteres, usando conteúdo dinâmico. No entanto, como é melhor separar a marcação dos dados, é melhor inserir a marcação em um modelo e manter os dados no código.

  1. Para iniciantes, edite views.py para que ela contenha o seguinte código que usa HTML embutido para a página com algum conteúdo dinâmico:

    from datetime import datetime
    from flask import render_template
    from HelloFlask import app
    
    @app.route('/')
    @app.route('/home')
    def home():
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        html_content = "<html><head><title>Hello Flask</title></head><body>"
        html_content += "<strong>Hello Flask!</strong> on " + formatted_now
        html_content += "</body></html>"
    
        return html_content
    
  2. Execute o aplicativo e atualize a página poucas vezes para ver que a data/hora está atualizada. Interrompa o aplicativo ao terminar.

  3. Para converter a renderização da página para usar um modelo, crie um arquivo chamado index.html na pasta templates com o seguinte conteúdo, em que {{ content }} é um espaço reservado ou um token de substituição (também chamado de uma variável de modelo) para o qual você fornece um valor no código:

    <html>
      <head>
        <title>Hello Flask</title>
      </head>
    
      <body>
        {{ content }}
      </body>
    </html>
    
  4. Modifique a função home para usar render_template para carregar o modelo e fornecer um valor para "conteúdo", que é feito usando um argumento nomeado correspondente ao nome do espaço reservado. O Flask procura automaticamente os modelos na pasta templates; portanto o caminho para o modelo é relativo a essa pasta:

    def home():
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        return render_template(
            "index.html",
            content = "<strong>Hello, Flask!</strong> on " + formatted_now)
    
  5. Execute o aplicativo e veja os resultados. Observe que o HTML embutido no valor content não é renderizado como HTML, porque o mecanismo de modelagem (Jinja) ignora automaticamente o conteúdo HTML. O escape automático impede vulnerabilidades acidentais a ataques de injeção. Os desenvolvedores geralmente coletam entradas de uma página e a usam como um valor em outra por meio de um espaço reservado de modelo. O escape também funciona como um lembrete de que é melhor manter o HTML fora do código.

    Da mesma forma, examine templates\index.html para conter espaços reservados distintos em cada parte dos dados dentro da marcação:

    <html>
      <head>
        <title>{{ title }}</title>
      </head>
      <body>
        <strong>{{ message }}</strong>{{ content }}
      </body>
    </html>
    

    Em seguida, atualize a função home para fornecer valores para todos os espaços reservados:

    def home():
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        return render_template(
            "index.html",
            title = "Hello Flask",
            message = "Hello, Flask!",
            content = " on " + formatted_now)
    
  6. Execute o aplicativo novamente e veja a saída renderizada corretamente.

    Running app using the template

  7. Você pode confirmar suas alterações no controle do código-fonte e atualizar seu repositório remoto. Para obter mais informações, consulte a etapa 2-1.

Pergunta: Os modelos de página precisam ficar em um arquivo separado?

Resposta: Embora os modelos geralmente sejam mantidos em arquivos HTML separados, também é possível usar um modelo embutido. É recomendável usar arquivos separados para manter uma separação clara entre o markup e o código.

Pergunta: Os modelos precisam usar a extensão de arquivo .html?

Resposta: A extensão .html dos arquivos de modelo de página é totalmente opcional, porque você sempre pode identificar o caminho relativo exato para o arquivo no primeiro argumento para a função render_template. No entanto, o Visual Studio (e outros editores) costuma fornecer funcionalidades como preenchimento de código e coloração de sintaxe com arquivos .html, o que supera o fato de os modelos de página não serem HTML.

Quando você está trabalhando com um projeto do Flask, o Visual Studio detecta automaticamente quando o arquivo HTML que você está editando é, na verdade, um modelo do Flask e fornece algumas funcionalidades de preenchimento automático. Por exemplo, quando você começa a digitar um comentário no modelo de página do Flask, {#, o Visual Studio fornece automaticamente os caracteres de fechamento #}. Os comandos Comentar Seleção e Remover Marca de Comentário da Seleção (no menu Editar>Avançado e na barra de ferramentas) também usam comentários de modelo em vez de comentários em HTML.

Pergunta: Os modelos podem ser organizados em subpastas adicionais?

Resposta: Sim. É possível usar subpastas e, em seguida, referir-se ao caminho relativo em templates nas chamadas a render_template. Isso é uma ótima maneira de criar efetivamente namespaces para os modelos.

Próximas etapas

Aprofunde-se um pouco mais