Como Usar Flask-SQLAlchemy para Interagir com Bancos de Dados em uma Aplicação Flask

O autor selecionou o Fundo de Software Livre e de Código Aberto para receber uma doação como parte do programa Escreva para Doações.

Introdução

Nas aplicações web, geralmente é necessário um banco de dados, que é uma coleção organizada de dados. Você usa um banco de dados para armazenar e manter dados persistentes que podem ser recuperados e manipulados de forma eficiente. Por exemplo, em uma aplicação de mídia social, você tem um banco de dados onde os dados do usuário (informações pessoais, postagens, comentários, seguidores) são armazenados de uma forma que pode ser manipulada de forma eficiente. Você pode adicionar dados a um banco de dados, recuperá-los, modificá-los ou excluí-los, dependendo de diferentes requisitos e condições. Em uma aplicação web, esses requisitos podem ser um usuário adicionando uma nova postagem, excluindo uma postagem ou excluindo sua conta, o que pode ou não excluir suas postagens. As ações que você realiza para manipular dados dependerão de recursos específicos em sua aplicação. Por exemplo, você pode não querer que os usuários adicionem postagens sem títulos.

Implante suas aplicações Flask do GitHub usando Plataforma de Aplicativos DigitalOcean. Deixe a DigitalOcean focar em dimensionar sua aplicação.

O Flask é um framework web leve em Python que fornece ferramentas e recursos úteis para criar aplicativos web na linguagem Python. SQLAlchemy é uma toolkit SQL que fornece acesso eficiente e de alto desempenho a bancos de dados relacionais. Ele fornece maneiras de interagir com vários motores de banco de dados, como SQLite, MySQL e PostgreSQL. Ele lhe dá acesso às funcionalidades SQL do banco de dados. Ele também fornece um Object Relational Mapper (ORM), que permite que você faça consultas e manipule dados usando objetos e métodos simples em Python. Flask-SQLAlchemy é uma extensão do Flask que torna o uso do SQLAlchemy com o Flask mais fácil, fornecendo ferramentas e métodos para interagir com seu banco de dados em seus aplicativos Flask por meio do SQLAlchemy.

Pré-requisitos

Um ambiente de programação Python 3 local. Siga o tutorial para a sua distribuição na série . Neste tutorial, chamaremos nosso diretório de projeto de flask_app.

Passo 1 — Instalando Flask e Flask-SQLAlchemy

Neste passo, você instalará os pacotes necessários para o seu aplicativo.

Com o ambiente virtual ativado, use pip para instalar Flask e Flask-SQLAlchemy:

  1. pip install Flask Flask-SQLAlchemy

Após a conclusão bem-sucedida da instalação, você verá uma linha semelhante à seguinte no final da saída:

Output
Successfully installed Flask-2.0.3 Flask-SQLAlchemy-2.5.1 Jinja2-3.0.3 MarkupSafe-2.1.0 SQLAlchemy-1.4.31 Werkzeug-2.0.3 click-8.0.4 greenlet-1.1.2 itsdangerous-2.1.0

Com os pacotes Python necessários instalados, você configurará o banco de dados a seguir.

Passo 2 — Configurando o Banco de Dados e o Modelo

Neste passo, você configurará a conexão com o banco de dados e criará um modelo de banco de dados SQLAlchemy, que é uma classe Python que representa a tabela que armazena seus dados. Você iniciará o banco de dados, criará uma tabela para alunos com base no modelo que declarará e adicionará alguns alunos em sua tabela de alunos.

Configurando a Conexão com o Banco de Dados

Abra um arquivo chamado app.py na sua pasta flask_app. Este arquivo conterá o código para configurar o banco de dados e suas rotas Flask:

  1. nano app.py

Este arquivo se conectará a um banco de dados SQLite chamado database.db e terá uma classe chamada Student que representa a tabela de estudantes do seu banco de dados para armazenar informações sobre os estudantes, além de suas rotas Flask. Adicione as seguintes instruções import no topo de app.py:

flask_app/app.py
import os
from flask import Flask, render_template, request, url_for, redirect
from flask_sqlalchemy import SQLAlchemy

from sqlalchemy.sql import func

Aqui, você importa o os módulo, que lhe dá acesso a interfaces variadas de sistema operacional. Você usará isso para construir um caminho de arquivo para o seu arquivo de banco de dados database.db.

Da flask pacote, você então importa os auxiliares necessários para o seu aplicativo: a Flask classe para criar uma instância de aplicativo Flask, a render_template() função para renderizar templates, o request objeto para lidar com solicitações, a url_for() função para construir URLs para rotas e a redirect() função para redirecionar usuários. Para mais informações sobre rotas e templates, consulte Como Usar Templates em um Aplicativo Flask.

Em seguida, você importa a classe SQLAlchemy do extensor Flask-SQLAlchemy, o que lhe dá acesso a todas as funções e classes do SQLAlchemy, além de auxiliares e funcionalidades que integram o Flask com o SQLAlchemy. Você usará isso para criar um objeto de banco de dados que se conecta ao seu aplicativo Flask, permitindo que você crie e manipule tabelas usando classes, objetos e funções Python, sem precisar usar a linguagem SQL.

Você também importa o auxiliar func do módulo sqlalchemy.sql para acessar funções SQL. Você precisará disso em seu sistema de gerenciamento de alunos para definir uma data e hora de criação padrão para quando um registro de aluno é criado.

Logo abaixo das importações, você configurará um caminho de arquivo de banco de dados, instanciará seu aplicativo Flask e configurará e conectará seu aplicativo com o SQLAlchemy. Adicione o seguinte código:

flask_app/app.py

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
        'sqlite:///' + os.path.join(basedir, 'database.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

Aqui, você constrói um caminho para o arquivo de banco de dados SQLite. Primeiro, define um diretório base como o diretório atual. Você usa a os.path.abspath() função para obter o caminho absoluto do diretório atual do arquivo. A variável especial __file__ contém o nome do caminho do arquivo atual app.py. Você armazena o caminho absoluto do diretório base em uma variável chamada basedir.

SQLALCHEMY_DATABASE_URI: O URI do banco de dados para especificar o banco de dados com o qual você deseja estabelecer uma conexão. Neste caso, o URI segue o formato sqlite:///caminho/para/banco_de_dados.db. Você usa a função os.path.join() para juntar inteligentemente o diretório base que você construiu e armazenou na variável basedir, e o nome do arquivo database.db. Isso conectará a um arquivo de banco de dados database.db em seu diretório flask_app. O arquivo será criado assim que você iniciar o banco de dados.

  • SQLALCHEMY_TRACK_MODIFICATIONS: Uma configuração para habilitar ou desabilitar o rastreamento de modificações de objetos. Você define como False para desabilitar o rastreamento e usar menos memória. Para mais informações, consulte a página de configuração na documentação do Flask-SQLAlchemy.

  • SQLALCHEMY_TRACK_MODIFICAÇÕES: Uma configuração para habilitar ou desabilitar o rastreamento de modificações de objetos. Você define isso como False para desabilitar o rastreamento e usar menos memória. Para mais informações, consulte a página de configuração na documentação do Flask-SQLAlchemy.

Nota:

Se você deseja usar outro mecanismo de banco de dados, como PostgreSQL ou MySQL, você precisará usar o URI apropriado.

Para PostgreSQL, use o seguinte formato:

postgresql://username:password@host:port/database_name

Para MySQL:

mysql://username:password@host:port/database_name

Para mais informações, consulte a documentação do SQLAlchemy para configuração do mecanismo de banco de dados.

Após configurar o SQLAlchemy, definindo um URI de banco de dados e desabilitando o rastreamento, você cria um objeto de banco de dados usando a classe SQLAlchemy, passando a instância do aplicativo para conectar seu aplicativo Flask com o SQLAlchemy. Você armazena seu objeto de banco de dados em uma variável chamada db. Você usará esse objeto db para interagir com seu banco de dados.

Declarando a Tabela

Com a conexão com o banco de dados estabelecida e o objeto do banco de dados criado, você usará o objeto do banco de dados para criar uma tabela para estudantes, que é representada por um modelo — uma classe Python que herda de uma classe base que o Flask-SQLAlchemy fornece através da instância de banco de dados db que você criou anteriormente. Para definir uma tabela de estudantes como um modelo, adicione a seguinte classe ao seu arquivo app.py:

flask_app/app.py
# ...

class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(100), nullable=False)
    lastname = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(80), unique=True, nullable=False)
    age = db.Column(db.Integer)
    created_at = db.Column(db.DateTime(timezone=True),
                           server_default=func.now())
    bio = db.Column(db.Text)

    def __repr__(self):
        return f'<Student {self.firstname}>'

Aqui, você cria um modelo Student, que herda da classe db.Model. Isso representa a tabela de estudantes. Você usa a classe db.Column para definir colunas para sua tabela. O primeiro argumento representa o tipo de coluna e argumentos adicionais representam a configuração da coluna.

Você define as seguintes colunas para o modelo Student:

  • id: O ID do estudante. Você o define como um inteiro com db.Integer. primary_key=True define essa coluna como uma chave primária, que atribuirá um valor único pelo banco de dados para cada entrada (ou seja, um estudante).
  • firstname: O primeiro nome do estudante. Uma string com um comprimento máximo de 100 caracteres. nullable=False indica que essa coluna não deve estar vazia.
  • sobrenome: O sobrenome do aluno. Uma string com um comprimento máximo de 100 caracteres. nullable=False significa que esta coluna não deve estar vazia.
  • email: O email do aluno. Uma string com um comprimento máximo de 80 caracteres. unique=True significa que cada email deve ser único para cada aluno. nullable=False significa que esta coluna não deve estar vazia.
  • idade: A idade do aluno.
  • created_at: O horário em que a entrada do aluno foi criada no banco de dados. Você usa db.DateTime para defini-lo como um objeto Python datetime. timezone=True habilita o suporte a fuso horário. server_default define o valor padrão no banco de dados ao criar a tabela, para que os valores padrão sejam tratados pelo banco de dados em vez do modelo. Você passa a função func.now(), que chama a função SQL now() para data e hora. No SQLite, é renderizado como CURRENT_TIMESTAMP ao criar a tabela de alunos.
  • bio: A bio do estudante. db.Text() indica que a coluna contém textos longos.

Consulte a documentação do SQLAlchemy para tipos de coluna diferentes dos tipos que você usou no bloco de código anterior.

A função especial __repr__ permite que você dê a cada objeto uma representação em string para reconhecê-lo para fins de depuração. Neste caso, você usa o primeiro nome do estudante.

O arquivo app.py agora ficará da seguinte forma:

flask_app/app.py
import os
from flask import Flask, render_template, request, url_for, redirect
from flask_sqlalchemy import SQLAlchemy

from sqlalchemy.sql import func


basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
        'sqlite:///' + os.path.join(basedir, 'database.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)


class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    firstname = db.Column(db.String(100), nullable=False)
    lastname = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(80), unique=True, nullable=False)
    age = db.Column(db.Integer)
    created_at = db.Column(db.DateTime(timezone=True),
                           server_default=func.now())
    bio = db.Column(db.Text)

    def __repr__(self):
        return f'<Student {self.firstname}>'

Salve e feche o arquivo app.py.

Criando o Banco de Dados

Agora que você definiu a conexão com o banco de dados e o modelo do estudante, usará o shell do Flask para criar seu banco de dados e sua tabela de estudantes com base no modelo Student.

Com o ambiente virtual ativado, defina o arquivo app.py como sua aplicação Flask usando a variável de ambiente FLASK_APP. Em seguida, abra o shell do Flask usando o seguinte comando em seu diretório flask_app:

  1. export FLASK_APP=app
  2. flask shell

A Python interactive shell will be opened. This special shell runs commands in the context of your Flask application, so that the Flask-SQLAlchemy functions you’ll call are connected to your application.

Importe o objeto de banco de dados e o modelo de aluno, e então execute a função db.create_all() para criar as tabelas associadas aos seus modelos. Neste caso, você possui apenas um modelo, o que significa que a chamada de função criará apenas uma tabela em seu banco de dados:

  1. from app import db, Student
  2. db.create_all()

Deixe o shell em execução, abra outra janela de terminal e navegue até o diretório flask_app. Agora você verá um novo arquivo chamado database.db no flask_app.

Nota:

A função db.create_all() não recria ou atualiza uma tabela se ela já existir. Por exemplo, se você modificar seu modelo adicionando uma nova coluna e executar a função db.create_all(), a alteração que você faz no modelo não será aplicada à tabela se a tabela já existir no banco de dados. A solução é excluir todas as tabelas de banco de dados existentes com a função db.drop_all() e, em seguida, recriá-las com a função db.create_all() da seguinte maneira:

  1. db.drop_all()
  2. db.create_all()

Isso aplicará as modificações que você faz aos seus modelos, mas também excluirá todos os dados existentes no banco de dados. Para atualizar o banco de dados e preservar os dados existentes, você precisará usar migração de esquema, que permite modificar suas tabelas e preservar dados. Você pode usar a extensão Flask-Migrate para realizar migrações de esquema SQLAlchemy através da interface de linha de comando do Flask.

Se você receber um erro, verifique se sua URI do banco de dados e sua declaração do modelo estão corretas.

Preenchendo a Tabela

Após criar o banco de dados e a tabela de alunos, você usará o shell do Flask para adicionar alguns alunos ao seu banco de dados através do modelo Student.

Use o mesmo shell do Flask que abriu anteriormente, ou abra um novo com seu ambiente virtual ativado em seu diretório flask_app:

  1. flask shell

Para adicionar um aluno ao seu banco de dados, você importará o objeto do banco de dados e o modelo Student, e criará uma instância do modelo Student, passando-lhe dados de aluno por meio de argumentos de palavra-chave da seguinte forma:

  1. from app import db, Student
  2. student_john = Student(firstname='john', lastname='doe',
  3. email='[email protected]', age=23,
  4. bio='Biology student')

O objeto student_john representa um aluno que será adicionado ao banco de dados, mas esse objeto ainda não foi escrito no banco de dados. Confira o objeto no shell do Flask para ver sua string de representação que você construiu com o método __repr__():

  1. student_john

Você receberá a seguinte saída:

Output
<Student john>

Você pode obter o valor das colunas usando os atributos de classe que definiu no modelo Student:

  1. student_john.firstname
  2. student_john.bio
Output
'john' 'Biology student'

Como esse aluno ainda não foi adicionado ao banco de dados, seu ID será None:

  1. print(student_john.id)
Output
None

Para adicionar este estudante ao banco de dados, você primeiro precisará adicioná-lo a uma sessão de banco de dados, que gerencia uma transação de banco de dados. O Flask-SQLAlchemy fornece o objeto db.session através do qual você pode gerenciar suas alterações no banco de dados. Adicione o objeto student_john à sessão usando o método db.session.add() para prepará-lo para ser escrito no banco de dados:

  1. db.session.add(student_john)

Isso emitirá uma instrução INSERT, mas você não receberá um ID de volta porque a transação do banco de dados ainda não foi confirmada. Para confirmar a transação e aplicar a mudança no banco de dados, use o método db.session.commit():

  1. db.session.commit()

Agora que o estudante John foi adicionado ao banco de dados, você pode obter seu ID:

  1. print(student_john.id)
Output
1

Você também pode usar o método db.session.add() para editar um item no banco de dados. Por exemplo, você pode modificar o e-mail do estudante da seguinte maneira:

  1. student_john.email = '[email protected]'
  2. db.session.add(student_john)
  3. db.session.commit()

Use o shell do Flask para adicionar mais alguns estudantes ao seu banco de dados:

  1. sammy = Student(firstname='Sammy',
  2. lastname='Shark',
  3. email='[email protected]',
  4. age=20,
  5. bio='Marine biology student')
  6. carl = Student(firstname='Carl',
  7. lastname='White',
  8. email='[email protected]',
  9. age=22,
  10. bio='Marine geology student')
  11. db.session.add(sammy)
  12. db.session.add(carl)
  13. db.session.commit()

Agora, você pode consultar todos os registros na tabela de estudantes usando o atributo query com o método all():

  1. Student.query.all()

Você receberá a seguinte saída:

Output
[<Student john>, <Student Sammy>, <Student Carl>]

Neste ponto, você tem três estudantes em seu banco de dados. Em seguida, você criará uma rota do Flask para a página inicial e exibirá todos os estudantes em seu banco de dados nela.

Etapa 3 — Exibindo Todos os Registros

Neste passo, você criará uma rota e um modelo para exibir todos os alunos no banco de dados na página inicial.

Deixe o shell do Flask em execução e abra uma nova janela de terminal.

Abra o seu arquivo app.py para adicionar uma rota para a página inicial:

  1. nano app.py

Adicione a seguinte rota no final do arquivo:

flask_app/app.py

# ...

@app.route('/')
def index():
    students = Student.query.all()
    return render_template('index.html', students=students)

Salve e feche o arquivo.

Aqui, você cria uma função de visualização index() usando o decorador app.route(). Nesta função, você consulta o banco de dados e obtém todos os alunos usando o modelo Student com o atributo query, que permite recuperar um ou mais itens do banco de dados usando diferentes métodos. Você usa o método all() para obter todas as entradas de alunos no banco de dados. Você armazena o resultado da consulta em uma variável chamada students e a passa para um modelo chamado index.html que você renderiza usando a função auxiliar render_template().

Antes de criar o arquivo de modelo index.html no qual você exibirá os alunos existentes no banco de dados, primeiro criará um modelo base, que terá todo o código HTML básico que outros modelos também usarão para evitar a repetição de código. Em seguida, você criará o arquivo de modelo index.html que renderizou em sua função index(). Para saber mais sobre modelos, consulte Como usar modelos em um aplicativo Flask.

Crie um diretório templates, em seguida, abra um novo modelo chamado base.html:

  1. mkdir templates
  2. nano templates/base.html

Adicione o seguinte código dentro do arquivo base.html:

flask_app/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .title {
            margin: 5px;
        }

        .content {
            margin: 5px;
            width: 100%;
            display: flex;
            flex-direction: row;
            flex-wrap: wrap;
        }

        .student {
            flex: 20%;
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3;
            inline-size: 100%;
        }

        .bio {
            padding: 10px;
            margin: 5px;
            background-color: #ffffff;
            color: #004835;
        }

        .name a {
            color: #00a36f;
            text-decoration: none;
        }

        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">Create</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

Salve e feche o arquivo.

Este modelo base possui todo o código HTML padrão que você precisará reutilizar em seus outros modelos. O bloco title será substituído para definir um título para cada página e o bloco content será substituído com o conteúdo de cada página. A barra de navegação possui três links: um para a página inicial, que vincula à função de visualização index() usando a função auxiliar url_for(), um para uma página Criar e um para uma página Sobre caso você opte por adicionar uma ao seu aplicativo. Você editará este arquivo mais tarde depois de adicionar uma página para criar novos alunos para tornar o link Criar funcional.

Em seguida, abra um novo arquivo de modelo index.html. Este é o modelo que você referenciou no arquivo app.py:

  1. nano templates/index.html

Adicione o seguinte código a ele:

flask_app/templates/index.html
{% extends 'base.html' %}

{% block content %}
    <h1 class="title">{% block title %} Students {% endblock %}</h1>
    <div class="content">
        {% for student in students %}
            <div class="student">
                <p><b>#{{ student.id }}</b></p>
                <b>
                    <p class="name">{{ student.firstname }} {{ student.lastname }}</p>
                </b>
                <p>{{ student.email }}</p>
                <p>{{ student.age }} years old.</p>
                <p>Joined: {{ student.created_at }}</p>
                <div class="bio">
                    <h4>Bio</h4>
                    <p>{{ student.bio }}</p>
                </div>
            </div>
        {% endfor %}
    </div>
{% endblock %}

Salve e feche o arquivo.

Aqui, você estende o template base e substitui o conteúdo do bloco de conteúdo. Você usa um título que também serve como um cabeçalho <h1>. Você usa um loop for Jinja na linha {% for student in students %} para percorrer cada estudante na variável students que você passou da função de visualização index() para este modelo. Você exibe o ID do aluno, seu primeiro e último nome, e-mail, idade, a data em que foram adicionados ao banco de dados e sua biografia.

Enquanto estiver na sua pasta flask_app com o ambiente virtual ativado, informe o Flask sobre o aplicativo (app.py neste caso) usando a variável de ambiente FLASK_APP. Em seguida, defina a variável de ambiente FLASK_ENV para development para executar o aplicativo no modo de desenvolvimento e obter acesso ao depurador. Para obter mais informações sobre o depurador do Flask, consulte Como lidar com erros em um aplicativo Flask. Use os seguintes comandos para fazer isso:

  1. export FLASK_APP=app
  2. export FLASK_ENV=development

Em seguida, execute o aplicativo:

  1. flask run

Com o servidor de desenvolvimento em execução, visite a seguinte URL usando seu navegador:

http://127.0.0.1:5000/

Você verá os alunos que adicionou ao banco de dados em uma página semelhante à seguinte:

Você exibiu os alunos que possui no banco de dados na página inicial. Em seguida, você criará uma rota para uma página de aluno, onde poderá exibir os detalhes de cada aluno individual.

Passo 4 — Exibindo um Único Registro

Neste passo, você usará o shell do Flask para consultar alunos por seu ID e criar uma rota e um modelo para exibir os detalhes de cada aluno em uma página dedicada.

No final deste passo, a URL http://127.0.0.1:5000/1 será uma página que exibe o primeiro aluno (porque tem o ID 1). A URL http://127.0.0.1:5000/ID exibirá o post com o ID associado, se existir.

Deixe o servidor de desenvolvimento em execução e abra uma nova janela de terminal.

Abra o shell do Flask para uma demonstração de como consultar alunos:

  1. flask shell

Para consultar registros e recuperar dados do banco de dados, Flask-SQLAlchemy fornece um atributo query na classe do modelo. Você pode usar seus métodos para obter registros com um filtro específico.

Por exemplo, você pode usar o método filter_by() com um parâmetro como firstname que corresponda a uma coluna na tabela com um argumento para recuperar um aluno específico:

  1. from app import db, Student
  2. Student.query.filter_by(firstname='Sammy').all()
Output
[<Student Sammy>]

Aqui você recupera todos os alunos com Sammy como seu primeiro nome. Você usa o método all() para obter uma lista de todos os resultados. Para obter o primeiro resultado, que é o único resultado aqui, você pode usar o método first():

  1. Student.query.filter_by(firstname='Sammy').first()
Output
<Student Sammy>

Para obter um aluno por seu ID, você pode usar filter_by(id=ID):

  1. Student.query.filter_by(id=3).first()

Ou, você pode usar o método mais curto get(), que permite recuperar um item específico usando sua chave primária:

  1. Student.query.get(3)

Ambos darão a mesma saída:

Output
<Student Carl>

Agora você pode sair do shell:

  1. exit()

Para recuperar um estudante pelo seu ID, você criará uma nova rota que renderiza uma página para cada estudante individual. Você usará o método get_or_404() que o Flask-SQLAlchemy fornece, que é uma variante do método get(). A diferença é que get() retorna o valor None quando nenhum resultado corresponde ao ID fornecido, e get_or_404() retorna uma resposta HTTP 404 Not Found. Abra o app.py para modificação:

  1. nano app.py

Adicione a seguinte rota no final do arquivo:

flask_app/app.py
# ...

@app.route('/<int:student_id>/')
def student(student_id):
    student = Student.query.get_or_404(student_id)
    return render_template('student.html', student=student)

Salve e feche o arquivo.

Aqui, você usa a rota '/<int:student_id>/', com int: sendo um conversor que converte a string padrão na URL em um número inteiro. E student_id é a variável de URL que determinará o estudante que será exibido na página.

Digite o seguinte código neste novo arquivo student.html. Isso será semelhante ao modelo index.html, exceto que ele só exibirá um único aluno:

Salve e feche o arquivo.

Neste arquivo, você estende o modelo base, definindo o nome completo do aluno como título da página. Você exibe o ID do aluno, o primeiro e último nome do aluno, e-mail, idade, data de criação do registro e a biografia deles.

  1. nano templates/student.html

Use seu navegador para navegar até a URL do segundo aluno:

flask_app/templates/student.html
{% extends 'base.html' %}

{% block content %}
    <span class="title">
        <h1>{% block title %} {{ student.firstname }} {{ student.lastname }}{% endblock %}</h1>
    </span>
    <div class="content">
            <div class="student">
                <p><b>#{{ student.id }}</b></p>
                <b>
                    <p class="name">{{ student.firstname }} {{ student.lastname }}</p>
                </b>
                <p>{{ student.email }}</p>
                <p>{{ student.age }} years old.</p>
                <p>Joined: {{ student.created_at }}</p>
                <div class="bio">
                    <h4>Bio</h4>
                    <p>{{ student.bio }}</p>
                </div>
            </div>
    </div>
{% endblock %}

Você verá uma página semelhante à seguinte:

Agora, edite o index.html para fazer com que cada nome de aluno seja um link para sua página:

Edite o loop for para parecer o seguinte:

http://127.0.0.1:5000/2

Salve e feche o arquivo.

Você adicionou uma tag <a> ao nome completo do aluno que vincula à página do aluno usando a função url_for(), passando o ID do aluno armazenado em student.id para a função de visualização student().

  1. nano templates/index.html

Navegue até sua página inicial ou atualize-a:

flask_app/templates/index.html
{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
    </div>
{% endfor %}

Agora, você verá que cada nome de aluno vincula à página do aluno apropriada.Depois de criar uma página para alunos individuais, você adicionará em seguida uma página para adicionar novos alunos ao banco de dados.Passo 5 — Criando um Novo Registro

Você adicionou uma tag <a> ao nome completo do aluno que faz o link para a página do aluno usando a função url_for(), passando o ID do aluno que está armazenado em student.id para a função de visualização student().

Navegue até a sua página inicial ou atualize-a:

http://127.0.0.1:5000/

Agora você verá que cada nome de aluno faz o link para a página do aluno apropriada.

Após criar uma página para alunos individuais, você adicionará uma página para adicionar novos alunos ao banco de dados.

Etapa 5 — Criando um Novo Registro

Nesta etapa, você adicionará uma nova rota ao seu aplicativo para adicionar novos alunos ao banco de dados usando formulários web.

Você renderizará uma página com um formulário web onde os usuários inserirão os dados do aluno. Em seguida, você lidará com a submissão do formulário, criará um objeto para o novo aluno usando o modelo Student, adicionará-o à sessão e, em seguida, confirmará a transação, de forma semelhante a como você adicionou entradas de alunos na Etapa 2.

Deixe o servidor de desenvolvimento em execução e abra uma nova janela de terminal.

Primeiro, abra o arquivo app.py:

  1. nano app.py

Adicione a seguinte rota no final do arquivo app.py:

flask_app/app.py
# ...


@app.route('/create/', methods=('GET', 'POST'))
def create():
    return render_template('create.html')

Salve e feche o arquivo.

Nesta rota, você passa a tupla ('GET', 'POST') para o parâmetro methods para permitir tanto solicitações GET quanto POST. As solicitações GET são usadas para recuperar dados do servidor. As solicitações POST são usadas para enviar dados para uma rota específica. Por padrão, apenas solicitações GET são permitidas. Quando o usuário solicita pela primeira vez a rota /create usando uma solicitação GET, um arquivo de modelo chamado create.html será renderizado. Você editará essa rota posteriormente para lidar com solicitações POST quando os usuários preencherem e enviarem o formulário da web para adicionar novos alunos.

Abra o novo modelo create.html:

  1. nano templates/create.html

Adicione o seguinte código a ele:

{% extends 'base.html' %}

{% block content %}
    <h1 style="width: 100%">{% block title %} Add a New Student {% endblock %}</h1>
    <form method="post">
        <p>
            <label for="firstname">First Name</label>
            <input type="text" name="firstname"
                   placeholder="First name">
            </input>
        </p>

        <p>
            <label for="lastname">Last Name</label>
            <input type="text" name="lastname"
                   placeholder="Last name">
            </input>
        </p>

        <p>
            <label for="email">Email</label>
            <input type="email" name="email"
                   placeholder="Student email">
            </input>
        </p>

        <p>
            <label for="age">Age</label>
            <input type="number" name="age"
                   placeholder="Age">
            </input>
        </p>

        <p>
        <label for="bio">Bio</label>
        <br>
        <textarea name="bio"
                  placeholder="Bio"
                  rows="15"
                  cols="60"
                  ></textarea>
        </p>
        <p>
            <button type="submit">Submit</button>
        </p>
    </form>
{% endblock %}

Salve e feche o arquivo.

Você estende o modelo base, define um título como cabeçalho e usa uma tag <form> com o atributo method definido como post para indicar que o formulário enviará uma solicitação POST.

Você tem dois campos de texto com os nomes firstname e lastname. Você usará esses nomes para acessar os dados do formulário que o usuário envia em sua função de visualização posteriormente.

Você tem um campo de email com o nome email, um campo numérico para a idade do aluno e uma área de texto para a biografia do aluno.

Por último, você tem um botão Enviar no final do formulário.

Agora, com o servidor de desenvolvimento em execução, use seu navegador para navegar até a rota /create:

http://127.0.0.1:5000/create

Você verá uma página Adicionar novo aluno com um formulário da web e um botão Enviar assim:

Se você preencher o formulário e enviá-lo, enviando uma solicitação POST para o servidor, nada acontece porque você não tratou solicitações POST na rota /create.

Abra app.py para lidar com a solicitação POST que o usuário envia:

  1. nano app.py

Edite a rota /create para ficar da seguinte maneira:

flask_app/app.py

@app.route('/create/', methods=('GET', 'POST'))
def create():
    if request.method == 'POST':
        firstname = request.form['firstname']
        lastname = request.form['lastname']
        email = request.form['email']
        age = int(request.form['age'])
        bio = request.form['bio']
        student = Student(firstname=firstname,
                          lastname=lastname,
                          email=email,
                          age=age,
                          bio=bio)
        db.session.add(student)
        db.session.commit()

        return redirect(url_for('index'))

    return render_template('create.html')

Salve e feche o arquivo.

Você lida com solicitações POST dentro da condição if request.method == 'POST'. Você extrai o nome, sobrenome, email, idade e biografia que o usuário envia do objeto request.form. Você converte a idade que é passada como uma string em um inteiro usando a função int() em Python. Você constrói um objeto student usando o modelo Student. Você adiciona o objeto aluno à sessão do banco de dados e, em seguida, confirma a transação.

Por fim, você redireciona o usuário para a página inicial onde eles podem ver o novo aluno adicionado abaixo dos alunos existentes.

Com o servidor de desenvolvimento em execução, use seu navegador para navegar até a rota /create:

http://127.0.0.1:5000/create

Preencha o formulário com alguns dados e envie-o.

Você será redirecionado para a página inicial onde verá seu aluno recém-adicionado.

Agora que você tem a funcionalidade para adicionar novos alunos, você precisará adicionar um link para a página Create na barra de navegação. Abra base.html:

  1. nano templates/base.html

Edite a tag <body> modificando o valor do atributo href para o link Create:

flask_app/templates/base.html
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="{{ url_for('create') }}">Create</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>

Salve e feche o arquivo.

Atualize a página inicial e você notará que o link Criar na barra de navegação agora está funcional.

Agora você tem uma página com um formulário web para adicionar novos alunos. Para obter mais informações sobre formulários web, consulte Como Usar Formulários Web em um Aplicativo Flask. Para um método mais avançado e seguro de gerenciar formulários web, consulte Como Usar e Validar Formulários Web com Flask-WTF. Em seguida, você adicionará uma página para editar os dados de alunos existentes.

Etapa 6 — Editar um Registro

Nesta etapa, você adicionará uma nova página ao seu aplicativo para editar dados de alunos existentes. Você adicionará uma nova rota /ID/edit/ para editar os dados de alunos com base em seu ID.

Abra o arquivo app.py:

  1. nano app.py

Adicione a seguinte rota ao final do arquivo. Isso recupera a entrada do aluno que você deseja editar usando seu ID. Ele extrai os novos dados do aluno enviados por meio de um formulário web que você criará mais tarde. Em seguida, ele edita os dados do aluno e redireciona o usuário para a página inicial:

flask_app/app.py
# ...


@app.route('/<int:student_id>/edit/', methods=('GET', 'POST'))
def edit(student_id):
    student = Student.query.get_or_404(student_id)

    if request.method == 'POST':
        firstname = request.form['firstname']
        lastname = request.form['lastname']
        email = request.form['email']
        age = int(request.form['age'])
        bio = request.form['bio']

        student.firstname = firstname
        student.lastname = lastname
        student.email = email
        student.age = age
        student.bio = bio

        db.session.add(student)
        db.session.commit()

        return redirect(url_for('index'))

    return render_template('edit.html', student=student)

Salve e feche o arquivo.

Você usa o método de consulta get_or_404() no modelo Student para obter o aluno associado ao ID de aluno fornecido. Isso responderá com um erro 404 Not Found caso nenhum aluno com o ID fornecido exista no banco de dados.

Se o ID fornecido tiver um aluno associado a ele, a execução do código continuará para a condição if request.method == 'POST'. Se a solicitação foi uma solicitação GET, o que significa que o usuário não enviou um formulário, então esta condição é falsa, e o código dentro dela será ignorado até a linha return render_template('edit.html', student=student). Isso renderiza um modelo edit.html, passando o objeto do aluno que você obteve do banco de dados, permitindo preencher o formulário web do aluno com os dados atuais do aluno. Você criará este modelo edit.html posteriormente.

Quando um usuário edita dados do aluno e envia o formulário, o código dentro do if request.method == 'POST' é executado. Você extrai os dados do aluno enviados do objeto request.form em variáveis correspondentes. Você define cada atributo do objeto student para os dados recém-enviados para alterar os valores das colunas como fez no Passo 2. Se nenhuma alteração foi realizada em um campo no formulário web, o valor dessa coluna permanecerá o mesmo no banco de dados.

Depois de definir os dados do aluno para os dados recém-enviados, você adiciona o objeto student à sessão do banco de dados, então você confirma as alterações. Por último, você redireciona o usuário para a página inicial.Em seguida, você precisa criar uma página onde os usuários possam fazer a edição. Abra um novo modelo edit.html:

Depois de definir os dados do aluno para os dados enviados recentemente, você adiciona o objeto student à sessão do banco de dados, então você confirma as alterações. Por fim, você redireciona o usuário para a página inicial.

Em seguida, você precisa criar uma página onde os usuários possam fazer edições. Abra um novo modelo edit.html:

  1. nano templates/edit.html

Este novo arquivo terá um formulário da web semelhante ao que está no arquivo create.html com os dados atuais do aluno como valores padrão para os campos. Adicione o seguinte código dentro dele:

flask_app/templates/edit.html

{% extends 'base.html' %}

{% block content %}
    <h1 style="width: 100%">
        {% block title %} Edit {{ student.firstname }}
                               {{ student.lastname }}'s Details
        {% endblock %}
    </h1>
    <form method="post">
        <p>
            <label for="firstname">First Name</label>
            <input type="text" name="firstname"
                   value={{ student.firstname }}
                   placeholder="First name">
            </input>
        </p>

        <p>
            <label for="lastname">Last Name</label>
            <input type="text" name="lastname"
                   value={{ student.lastname }}
                   placeholder="Last name">
            </input>
        </p>

        <p>
            <label for="email">Email</label>
            <input type="email" name="email"
                   value={{ student.email }}
                   placeholder="Student email">
            </input>
        </p>

        <p>
            <label for="age">Age</label>
            <input type="number" name="age"
                   value={{ student.age }}
                   placeholder="Age">
            </input>
        </p>

        <p>
        <label for="bio">Bio</label>
        <br>
        <textarea name="bio"
                  placeholder="Bio"
                  rows="15"
                  cols="60"
                  >{{ student.bio }}</textarea>
        </p>
        <p>
            <button type="submit">Submit</button>
        </p>
    </form>
{% endblock %}

Salve e feche o arquivo.

O título tem o primeiro nome e o sobrenome do aluno. O atributo value de cada campo de entrada e o valor do textarea de bio são definidos como o valor correspondente no objeto student que você passou da função de visualização edit() para o modelo edit.html.

Agora, navegue até a seguinte URL para editar os detalhes do primeiro aluno:

http://127.0.0.1:5000/1/edit

Você verá uma página semelhante à seguinte:

Edite os dados do aluno e envie o formulário. Você será redirecionado para a página inicial e as informações do aluno serão atualizadas.

Em seguida, você adicionará um botão Editar abaixo de cada aluno na página inicial para vincular à sua página de edição. Abra o arquivo de modelo index.html:

  1. nano templates/index.html

Edite o loop for neste arquivo index.html para parecer exatamente com o seguinte:

flask_app/templates/index.html

{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
        <a href="{{ url_for('edit', student_id=student.id) }}">Edit</a>
    </div>
{% endfor %}

Salve e feche o arquivo.

Aqui você adiciona uma tag <a> para vincular à função de visualização edit(), passando o valor student.id para vincular à página de edição de cada aluno com um link de Editar.

Agora você tem uma página para editar alunos existentes. Em seguida, você adicionará um botão Excluir para excluir alunos do banco de dados.

Passo 7 — Excluir um Registro

Neste passo, você adicionará uma nova rota e um botão Excluir para excluir alunos existentes.

Primeiro, você adicionará uma nova rota /id/delete que aceita solicitações POST. Sua nova função de visualização delete() receberá o ID do aluno que você deseja excluir, passará o ID para o método get_or_404() na consulta no modelo Student para obtê-lo se existir, ou responderá com uma página 404 Não Encontrado se nenhum aluno com o ID fornecido foi encontrado no banco de dados.

Abra o app.py para edição:

  1. nano app.py

Adicione a seguinte rota ao final do arquivo:

flask_app/app.py

# ...

@app.post('/<int:student_id>/delete/')
def delete(student_id):
    student = Student.query.get_or_404(student_id)
    db.session.delete(student)
    db.session.commit()
    return redirect(url_for('index'))

Salve e feche o arquivo.

Aqui, em vez de usar o habitual decorador app.route, você utiliza o decorador app.post introduzido na versão 2.0.0 do Flask, que adicionou atalhos para métodos HTTP comuns. Por exemplo, @app.post("/login") é um atalho para @app.route("/login", methods=["POST"]). Isso significa que esta função de visualização aceita apenas pedidos POST, e navegar para a rota /ID/delete no seu navegador retornará um erro 405 Method Not Allowed, porque os navegadores da web por padrão usam pedidos GET. Para excluir um aluno, o usuário clica em um botão que envia um pedido POST para esta rota.

Esta função de visualização delete() recebe o ID do aluno a ser excluído através da variável de URL student_id. Você utiliza o método get_or_404() para obter um aluno e salvá-lo em uma variável student, ou responde com um 404 Not Found caso o aluno não exista. Você utiliza o método delete() na sessão do banco de dados na linha db.session.delete(student), passando-lhe o objeto aluno. Isso configura a sessão para excluir o aluno sempre que a transação for confirmada. Como não é necessário fazer mais nenhuma modificação, você confirma diretamente a transação usando db.session.commit(). Por último, redireciona o usuário para a página inicial.

Em seguida, edite o modelo index.html para adicionar um botão Excluir Aluno:

  1. nano templates/index.html

Edite o for loop adicionando uma nova tag <form> diretamente abaixo do link Edit:

flask_app/templates/index.html

{% for student in students %}
    <div class="student">
        <p><b>#{{ student.id }}</b></p>
        <b>
            <p class="name">
                <a href="{{ url_for('student', student_id=student.id)}}">
                    {{ student.firstname }} {{ student.lastname }}
                </a>
            </p>
        </b>
        <p>{{ student.email }}</p>
        <p>{{ student.age }} years old.</p>
        <p>Joined: {{ student.created_at }}</p>
        <div class="bio">
            <h4>Bio</h4>
            <p>{{ student.bio }}</p>
        </div>
        <a href="{{ url_for('edit', student_id=student.id) }}">Edit</a>

        <hr>
        <form method="POST"
                action="{{ url_for('delete', student_id=student.id) }}">
            <input type="submit" value="Delete Student"
                onclick="return confirm('Are you sure you want to delete this entry?')">
        </form>

    </div>
{% endfor %}

Salve e feche o arquivo.

Aqui, você tem um formulário web que envia uma solicitação POST para a função de visualização delete(). Você passa student.id como um argumento para o parâmetro student_id para especificar a entrada do aluno a ser excluída. Você usa a função confirm() disponível nos navegadores da web para exibir uma mensagem de confirmação antes de enviar a solicitação.

Agora atualize sua página de índice.

Você verá um botão Delete Student abaixo de cada entrada de aluno. Clique nele e confirme a exclusão. Você será redirecionado para a página de índice e o aluno não estará mais lá.

Agora você tem uma maneira de excluir alunos do banco de dados em seu aplicativo de gerenciamento de alunos.

Conclusão

Você construiu um pequeno aplicativo web Flask para gerenciar alunos usando Flask e Flask-SQLAlchemy com um banco de dados SQLite. Você aprendeu como se conectar ao seu banco de dados, configurar modelos de banco de dados que representam suas tabelas, adicionar itens ao seu banco de dados, consultar sua tabela e modificar dados do banco de dados.

Usar o SQLAlchemy na sua aplicação permite que você use classes e objetos Python para gerenciar seu banco de dados SQL. Em vez do SQLite, você pode usar outro mecanismo de banco de dados e, além da configuração SQLALCHEMY_DATABASE_URI responsável pela conexão, você não precisa mudar nada no código principal da sua aplicação. Isso permite que você migre de um mecanismo de banco de dados SQL para outro com mínimas alterações de código. Consulte a documentação do Flask-SQLAlchemy para mais informações.

Se você deseja ler mais sobre o Flask, confira os outros tutoriais na série Como Construir Aplicações Web com Flask.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-flask-sqlalchemy-to-interact-with-databases-in-a-flask-application