Como Consultar Tabelas e Paginar Dados no Flask-SQLAlchemy

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

Introdução

O Flask é um framework leve de Python para web que fornece ferramentas úteis e recursos para criar aplicações web na linguagem Python. O SQLAlchemy é um conjunto de ferramentas SQL que fornece acesso eficiente e de alto desempenho a bancos de dados relacionais. Ele oferece maneiras de interagir com vários motores de banco de dados, como SQLite, MySQL e PostgreSQL. Ele fornece acesso às funcionalidades SQL do banco de dados. E também fornece um Mapeador Relacional de Objetos (ORM), que permite fazer consultas e manipular dados usando objetos e métodos simples de Python. O Flask-SQLAlchemy é uma extensão do Flask que facilita o uso do SQLAlchemy com o Flask, fornecendo ferramentas e métodos para interagir com seu banco de dados em suas aplicações Flask através do SQLAlchemy.

Neste tutorial, você usará Flask e Flask-SQLAlchemy para criar um sistema de gerenciamento de funcionários com um banco de dados que possui uma tabela para os funcionários. Cada funcionário terá um ID único, um primeiro nome, um sobrenome, um e-mail único, um valor inteiro para a idade, uma data para o dia em que ingressaram na empresa e um valor booleano para determinar se um funcionário está atualmente ativo ou fora do escritório.

Você usará o shell do Flask para consultar uma tabela e obter registros da tabela com base em um valor de coluna (por exemplo, um e-mail). Você recuperará os registros dos funcionários em certas condições, como obter apenas funcionários ativos ou obter uma lista de funcionários fora do escritório. Você ordenará os resultados por um valor de coluna, contará e limitará os resultados da consulta. Finalmente, você usará a paginação para exibir um certo número de funcionários por página em uma aplicação web.

Pré-requisitos

Passo 1 — Configurando o Banco de Dados e o Modelo

Neste passo, você instalará os pacotes necessários e configurará sua aplicação Flask, o banco de dados Flask-SQLAlchemy e o modelo de funcionário que representa a tabela employee onde você armazenará seus dados de funcionários. Você inserirá alguns funcionários na tabela employee e adicionará uma rota e uma página onde todos os funcionários são exibidos na página inicial da sua aplicação.

Primeiro, com seu ambiente virtual ativado, instale o Flask e o Flask-SQLAlchemy:

  1. pip install Flask Flask-SQLAlchemy

Depois que a instalação estiver completa, você receberá uma saída com a seguinte linha no final:

Output
Successfully installed Flask-2.1.2 Flask-SQLAlchemy-2.5.1 Jinja2-3.1.2 MarkupSafe-2.1.1 SQLAlchemy-1.4.37 Werkzeug-2.1.2 click-8.1.3 greenlet-1.1.2 itsdangerous-2.1.2

Com os pacotes necessários instalados, abra um novo arquivo chamado app.py no diretório flask_app. Este arquivo conterá o código para configurar o banco de dados e suas rotas Flask:

  1. nano app.py

Adicione o seguinte código ao app.py. Este código configurará um banco de dados SQLite e um modelo de banco de dados de funcionários representando a tabela employee que você usará para armazenar seus dados de funcionários:

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


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 Employee(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(100), unique=True, nullable=False)
    age = db.Column(db.Integer, nullable=False)
    hire_date = db.Column(db.Date, nullable=False)
    active = db.Column(db.Boolean, nullable=False)

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

Salve e feche o arquivo.

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

Do pacote flask, você importa os auxiliares necessários para sua aplicação: a classe Flask para criar uma instância de aplicativo Flask, render_template() para renderizar modelos, o objeto request para manipular solicitações, url_for() para construir URLs e a função redirect() para redirecionar usuários. Para mais informações sobre rotas e modelos, veja Como usar modelos em uma aplicação Flask.

Em seguida, você importa a classe SQLAlchemy da extensão Flask-SQLAlchemy, que lhe dá acesso a todas as funções e classes do SQLAlchemy, além de auxiliares e funcionalidades que integram Flask com SQLAlchemy. Você o utilizará para criar um objeto de banco de dados que se conecta à sua aplicação Flask.

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

Em seguida, você cria uma instância de aplicativo Flask chamada app, que você utiliza para configurar duas chaves de configuração do Flask-SQLAlchemy configuração:

  • 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/database.db. Você utiliza a função os.path.join() para juntar inteligentemente o diretório base que você construiu e armazenou na variável basedir com o nome do arquivo database.db. Isso irá conectar-se a um arquivo de banco de dados database.db no 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 desativar o rastreamento, o que utiliza menos memória. Para mais informações, consulte a página de configuração na documentação do Flask-SQLAlchemy.

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 da aplicação para conectar sua aplicação Flask com o SQLAlchemy. Você armazena o objeto de banco de dados em uma variável chamada db, que será utilizada para interagir com o banco de dados.

Depois de configurar a instância da aplicação e o objeto do banco de dados, você herda da classe db.Model para criar um modelo de banco de dados chamado Employee. Este modelo representa a tabela employee, e possui as seguintes colunas:

  • id: O ID do funcionário, uma chave primária do tipo inteiro.
  • firstname: O primeiro nome do funcionário, uma string com um comprimento máximo de 100 caracteres. nullable=False indica que esta coluna não pode estar vazia.
  • lastname: O sobrenome do funcionário, uma string com um comprimento máximo de 100 caracteres. nullable=False indica que esta coluna não pode estar vazia.
  • email: O email do funcionário, uma string com um comprimento máximo de 100 caracteres. unique=True indica que cada email deve ser único. nullable=False indica que o valor não pode estar vazio.
  • age: A idade do funcionário, um valor inteiro.
  • hire_date: A data em que o funcionário foi contratado. Você define db.Date como o tipo de coluna para declará-la como uma coluna que armazena datas.
  • active: Uma coluna que irá armazenar um valor booleano para indicar se o funcionário está atualmente ativo ou fora do escritório.

A função especial __repr__ permite dar a cada objeto uma representação de string para identificá-lo para fins de depuração. Neste caso, você utiliza o primeiro e o último nome do funcionário para representar cada objeto de funcionário.

Agora que você configurou a conexão com o banco de dados e o modelo de funcionário, você vai escrever um programa em Python para criar seu banco de dados e a tabela employee e preencher a tabela com alguns dados de funcionários.

Abra um novo arquivo chamado init_db.py no seu diretório flask_app:

  1. nano init_db.py

Adicione o seguinte código para excluir as tabelas de banco de dados existentes e começar com um banco de dados limpo, criar a tabela employee e inserir nove funcionários nela:

flask_app/init_db.py
from datetime import date
from app import db, Employee

db.drop_all()
db.create_all()

e1 = Employee(firstname='John',
              lastname='Doe',
              email='[email protected]',
              age=32,
              hire_date=date(2012, 3, 3),
              active=True
              )

e2 = Employee(firstname='Mary',
              lastname='Doe',
              email='[email protected]',
              age=38,
              hire_date=date(2016, 6, 7),
              active=True
              )

e3 = Employee(firstname='Jane',
              lastname='Tanaka',
              email='[email protected]',
              age=32,
              hire_date=date(2015, 9, 12),
              active=False
              )

e4 = Employee(firstname='Alex',
              lastname='Brown',
              email='[email protected]',
              age=29,
              hire_date=date(2019, 1, 3),
              active=True
              )

e5 = Employee(firstname='James',
              lastname='White',
              email='[email protected]',
              age=24,
              hire_date=date(2021, 2, 4),
              active=True
              )

e6 = Employee(firstname='Harold',
              lastname='Ishida',
              email='[email protected]',
              age=52,
              hire_date=date(2002, 3, 6),
              active=False
              )

e7 = Employee(firstname='Scarlett',
              lastname='Winter',
              email='[email protected]',
              age=22,
              hire_date=date(2021, 4, 7),
              active=True
              )

e8 = Employee(firstname='Emily',
              lastname='Vill',
              email='[email protected]',
              age=27,
              hire_date=date(2019, 6, 9),
              active=True
              )

e9 = Employee(firstname='Mary',
              lastname='Park',
              email='[email protected]',
              age=30,
              hire_date=date(2021, 8, 11),
              active=True
              )

db.session.add_all([e1, e2, e3, e4, e5, e6, e7, e8, e9])

db.session.commit()

Aqui, você importa a classe date() do módulo datetime para usá-la para definir as datas de contratação dos funcionários.

Você importa o objeto de banco de dados e o modelo Employee. Você chama a função db.drop_all() para excluir todas as tabelas existentes e evitar a chance de uma tabela employee já populada existir no banco de dados, o que poderia causar problemas. Isso exclui todos os dados do banco de dados sempre que você executa o programa init_db.py. Para obter mais informações sobre como criar, modificar e excluir tabelas de banco de dados, consulte Como usar o Flask-SQLAlchemy para interagir com bancos de dados em uma aplicação Flask.

Em seguida, você cria várias instâncias do modelo Employee, que representam os funcionários que você consultará neste tutorial, e os adiciona à sessão do banco de dados usando a função db.session.add_all(). Por fim, você confirma a transação e aplica as alterações ao banco de dados usando o db.session.commit().

Salve e feche o arquivo.

Execute o programa init_db.py:

  1. python init_db.py

Para dar uma olhada nos dados que você adicionou ao seu banco de dados, certifique-se de que seu ambiente virtual está ativado e abra o shell do Flask para consultar todos os funcionários e exibir seus dados:

  1. flask shell

Execute o seguinte código para consultar todos os funcionários e exibir seus dados:

  1. from app import db, Employee
  2. employees = Employee.query.all()
  3. for employee in employees:
  4. print(employee.firstname, employee.lastname)
  5. print('Email:', employee.email)
  6. print('Age:', employee.age)
  7. print('Hired:', employee.hire_date)
  8. if employee.active:
  9. print('Active')
  10. else:
  11. print('Out of Office')
  12. print('----')

Você usa o método all() do atributo query para obter todos os funcionários. Você percorre os resultados e exibe as informações do funcionário. Para a coluna active, você usa uma instrução condicional para exibir o status atual do funcionário, seja 'Ativo' ou 'Fora do Escritório'.

Você receberá a seguinte saída:

Output
John Doe Email: [email protected] Age: 32 Hired: 2012-03-03 Active ---- Mary Doe Email: [email protected] Age: 38 Hired: 2016-06-07 Active ---- Jane Tanaka Email: [email protected] Age: 32 Hired: 2015-09-12 Out of Office ---- Alex Brown Email: [email protected] Age: 29 Hired: 2019-01-03 Active ---- James White Email: [email protected] Age: 24 Hired: 2021-02-04 Active ---- Harold Ishida Email: [email protected] Age: 52 Hired: 2002-03-06 Out of Office ---- Scarlett Winter Email: [email protected] Age: 22 Hired: 2021-04-07 Active ---- Emily Vill Email: [email protected] Age: 27 Hired: 2019-06-09 Active ---- Mary Park Email: [email protected] Age: 30 Hired: 2021-08-11 Active ----

Você pode ver que todos os funcionários que adicionamos ao banco de dados estão sendo exibidos corretamente.

Saia do shell do Flask:

  1. exit()

Em seguida, você criará uma rota Flask para exibir os funcionários. Abra o arquivo app.py para edição:

  1. nano app.py

Adicione a seguinte rota no final do arquivo:

flask_app/app.py
...

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

Salve e feche o arquivo.

Isso consulta todos os funcionários, renderiza um modelo index.html e passa os funcionários que você obtém.

Crie um diretório de modelos e um modelo base:

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

Adicione o seguinte ao 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;
        }

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

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

        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

        .pagination {
            margin: 0 auto;
        }

        .pagination span {
            font-size: 2em;
            margin-right: 10px;
        }

        .page-number {
            color: #d64161;
            padding: 5px;
            text-decoration: none;
        }

        .current-page-number {
            color: #666
        }

    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

Salve e feche o arquivo.

Aqui, você utiliza um bloco de título e adiciona algum estilo CSS. Você adiciona uma barra de navegação com dois itens, um para a página inicial e outro para uma página Sobre inativa. Esta barra de navegação será reutilizada em toda a aplicação nos modelos que herdam deste modelo base. O bloco de conteúdo será substituído pelo conteúdo de cada página. Para mais informações sobre modelos, confira Como Usar Modelos em uma Aplicação Flask.

Em seguida, abra um novo modelo index.html que você renderizou em app.py:

  1. nano templates/index.html

Adicione o seguinte código ao arquivo:

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

{% block content %}
    <h1 class="title">{% block title %} Employees {% endblock %}</h1>
    <div class="content">
        {% for employee in employees %}
            <div class="employee">
                <p><b>#{{ employee.id }}</b></p>
                <b>
                    <p class="name">{{ employee.firstname }} {{ employee.lastname }}</p>
                </b>
                <p>{{ employee.email }}</p>
                <p>{{ employee.age }} years old.</p>
                <p>Hired: {{ employee.hire_date }}</p>
                {% if employee.active %}
                    <p><i>(Active)</i></p>
                {% else %}
                    <p><i>(Out of Office)</i></p>
                {% endif %}
            </div>
        {% endfor %}
    </div>
{% endblock %}

Aqui, você faz um loop pelos funcionários e exibe as informações de cada um. Se o funcionário estiver ativo, você adiciona uma etiqueta (Ativo), caso contrário, exibe uma etiqueta (Fora do Escritório).

Salve e feche o arquivo.

Enquanto estiver no diretório flask_app com o seu ambiente virtual ativado, informe ao Flask sobre a aplicação (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 a aplicação 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 uma Aplicação Flask. Use os seguintes comandos para fazer isso:

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

Em seguida, execute a aplicação:

  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 funcionários que foram adicionados ao banco de dados em uma página semelhante à seguinte:

Deixe o servidor em execução, abra outro terminal e continue para o próximo passo.

Você exibiu os funcionários que possui em seu banco de dados na página de índice. Em seguida, usará o shell do Flask para consultar funcionários usando diferentes métodos.

Passo 2 — Consultando Registros

Neste passo, você usará o shell do Flask para consultar registros e filtrar e recuperar resultados usando múltiplos métodos e condições.

Com seu ambiente de programação ativado, defina as variáveis FLASK_APP e FLASK_ENV e abra o shell do Flask:

  1. export FLASK_APP=app
  2. export FLASK_ENV=development
  3. flask shell

Importar o objeto db e o modelo Employee:

  1. from app import db, Employee

Recuperando Todos os Registros

Como visto no passo anterior, você pode usar o método all() no atributo query para obter todos os registros em uma tabela:

  1. all_employees = Employee.query.all()
  2. print(all_employees)

O resultado será uma lista de objetos representando todos os funcionários:

Output
[<Employee John Doe>, <Employee Mary Doe>, <Employee Jane Tanaka>, <Employee Alex Brown>, <Employee James White>, <Employee Harold Ishida>, <Employee Scarlett Winter>, <Employee Emily Vill>, <Employee Mary Park>]

Recuperando o Primeiro Registro

Da mesma forma, você pode usar o método first() para obter o primeiro registro:

  1. first_employee = Employee.query.first()
  2. print(first_employee)

O resultado será um objeto que contém os dados do primeiro funcionário:

Output
<Employee John Doe>

Recuperando um Registro por ID

Na maioria das tabelas de banco de dados, os registros são identificados com um ID único. O Flask-SQLAlchemy permite que você recupere um registro usando seu ID com o método get():

  1. employee5 = Employee.query.get(5)
  2. employee3 = Employee.query.get(3)
  3. print(f'{employee5} | ID: {employee5.id}')
  4. print(f'{employee3} | ID: {employee3.id}')
Output
<Employee James White> | ID: 5 <Employee Jane Tanaka> | ID: 3

Recuperando um Registro ou Múltiplos Registros por um Valor de Coluna

Para obter um registro usando o valor de uma de suas colunas, use o método filter_by(). Por exemplo, para obter um registro usando seu valor de ID, similar ao método get():

  1. employee = Employee.query.filter_by(id=1).first()
  2. print(employee)
Output
<Employee John Doe>

Você usa first() porque filter_by() pode retornar vários resultados.

Nota: Para obter um registro por ID, usar o método get() é uma abordagem melhor.

Por outro exemplo, você pode obter um funcionário usando sua idade:

  1. employee = Employee.query.filter_by(age=52).first()
  2. print(employee)
Output
<Employee Harold Ishida>

Para um exemplo em que o resultado da consulta contém mais de um registro correspondente, use a coluna firstname e o primeiro nome Mary, que é um nome compartilhado por dois funcionários:

  1. mary = Employee.query.filter_by(firstname='Mary').all()
  2. print(mary)
Output
[<Employee Mary Doe>, <Employee Mary Park>]

Aqui, você usa all() para obter a lista completa. Você também pode usar first() para obter apenas o primeiro resultado:

  1. mary = Employee.query.filter_by(firstname='Mary').first()
  2. print(mary)
Output
<Employee Mary Doe>

Você recuperou registros através de valores de colunas. Em seguida, você consultará sua tabela usando condições lógicas.

Passo 3 — Filtrando Registros Usando Condições Lógicas

Nas aplicações web complexas e completas, muitas vezes é necessário consultar registros do banco de dados usando condicionais complicados, como buscar funcionários com base em uma combinação de condições que levam em conta sua localização, disponibilidade, cargo e responsabilidades. Nesta etapa, você terá prática em usar operadores condicionais. Você usará o método filter() no atributo query para filtrar os resultados da consulta usando condições lógicas com diferentes operadores. Por exemplo, você pode usar operadores lógicos para obter uma lista de quais funcionários estão atualmente fora do escritório, ou funcionários que estão devido a uma promoção, e talvez fornecer um calendário de tempo de férias dos funcionários, etc.

Igualdade

O operador lógico mais simples que você pode usar é o operador de igualdade ==, que se comporta de forma semelhante ao filter_by(). Por exemplo, para obter todos os registros onde o valor da coluna firstname é Mary, você pode usar o método filter() assim:

  1. mary = Employee.query.filter(Employee.firstname == 'Mary').all()
  2. print(mary)

Aqui você usa a sintaxe Modelo.coluna == valor como argumento para o método filter(). O método filter_by() é um atalho para esta sintaxe.

O resultado é o mesmo que o resultado do método filter_by() com a mesma condição:

Output
[<Employee Mary Doe>, <Employee Mary Park>]

Assim como o filter_by(), você também pode usar o método first() para obter o primeiro resultado:

  1. mary = Employee.query.filter(Employee.firstname == 'Mary').first()
  2. print(mary)
Output
<Employee Mary Doe>

Diferente

O método filter() permite que você use o operador != do Python para obter registros. Por exemplo, para obter uma lista de funcionários fora do escritório, você pode usar a seguinte abordagem:

  1. out_of_office_employees = Employee.query.filter(Employee.active != True).all()
  2. print(out_of_office_employees)
Output
[<Employee Jane Tanaka>, <Employee Harold Ishida>]

Aqui você usa a condição Employee.active != True para filtrar os resultados.

Menor Que

Você pode usar o operador < para obter um registro onde o valor de uma determinada coluna é menor que o valor dado. Por exemplo, para obter uma lista de funcionários com menos de 32 anos:

  1. employees_under_32 = Employee.query.filter(Employee.age < 32).all()
  2. for employee in employees_under_32:
  3. print(employee.firstname, employee.lastname)
  4. print('Age: ', employee.age)
  5. print('----')
Output
Alex Brown Age: 29 ---- James White Age: 24 ---- Scarlett Winter Age: 22 ---- Emily Vill Age: 27 ---- Mary Park Age: 30 ----

Use o operador <= para registros que sejam menores ou iguais ao valor dado. Por exemplo, para incluir funcionários com 32 anos na consulta anterior:

  1. employees_32_or_younger = Employee.query.filter(Employee.age <=32).all()
  2. for employee in employees_32_or_younger:
  3. print(employee.firstname, employee.lastname)
  4. print('Age: ', employee.age)
  5. print('----')
Output
John Doe Age: 32 ---- Jane Tanaka Age: 32 ---- Alex Brown Age: 29 ---- James White Age: 24 ---- Scarlett Winter Age: 22 ---- Emily Vill Age: 27 ---- Mary Park Age: 30 ----

Maior Que

Da mesma forma, o operador > obtém um registro onde o valor de uma determinada coluna é maior que o valor dado. Por exemplo, para obter funcionários com mais de 32 anos:

  1. employees_over_32 = Employee.query.filter(Employee.age > 32).all()
  2. for employee in employees_over_32:
  3. print(employee.firstname, employee.lastname)
  4. print('Age: ', employee.age)
  5. print('----')
Output
Mary Doe Age: 38 ---- Harold Ishida Age: 52 ----

E o operador >= é para registros que sejam maiores ou iguais ao valor dado. Por exemplo, você pode novamente incluir funcionários de 32 anos na consulta anterior:

  1. employees_32_or_older = Employee.query.filter(Employee.age >=32).all()
  2. for employee in employees_32_or_older:
  3. print(employee.firstname, employee.lastname)
  4. print('Age: ', employee.age)
  5. print('----')
Output
John Doe Age: 32 ---- Mary Doe Age: 38 ---- Jane Tanaka Age: 32 ---- Harold Ishida Age: 52 ----

No

SQLAlchemy também fornece uma maneira de obter registros onde o valor de uma coluna corresponde a um valor de uma lista de valores usando o método in_() na coluna assim:

  1. names = ['Mary', 'Alex', 'Emily']
  2. employees = Employee.query.filter(Employee.firstname.in_(names)).all()
  3. print(employees)
Output
[<Employee Mary Doe>, <Employee Alex Brown>, <Employee Emily Vill>, <Employee Mary Park>]

Aqui, você usa uma condição com a sintaxe Modelo.coluna.in_(iterável), onde iterável é qualquer tipo de objeto pelo qual você pode iterar. Para outro exemplo, você pode usar a função Python range() para obter funcionários de uma faixa etária específica. A seguinte consulta obtém todos os funcionários que estão na faixa dos trinta anos.

  1. employees_in_30s = Employee.query.filter(Employee.age.in_(range(30, 40))).all()
  2. for employee in employees_in_30s:
  3. print(employee.firstname, employee.lastname)
  4. print('Age: ', employee.age)
  5. print('----')
Output
John Doe Age: 32 ---- Mary Doe Age: 38 ---- Jane Tanaka Age: 32 ---- Mary Park Age: 30 ----

Não Está Em

Similar ao método in_(), você pode usar o método not_in() para obter registros onde o valor de uma coluna não está em um iterável dado:

  1. names = ['Mary', 'Alex', 'Emily']
  2. employees = Employee.query.filter(Employee.firstname.not_in(names)).all()
  3. print(employees)
Output
[<Employee John Doe>, <Employee Jane Tanaka>, <Employee James White>, <Employee Harold Ishida>, <Employee Scarlett Winter>]

Aqui, você obtém todos os funcionários exceto aqueles com um primeiro nome na lista nomes.

E

Você pode unir várias condições usando a função db.and_(), que funciona como o operador e do Python.

Por exemplo, digamos que você queira obter todos os funcionários que têm 32 anos e estão atualmente ativos. Primeiro, você pode verificar quem tem 32 anos usando o método filter_by() (também pode usar filter() se preferir):

  1. for employee in Employee.query.filter_by(age=32).all():
  2. print(employee)
  3. print('Age:', employee.age)
  4. print('Active:', employee.active)
  5. print('-----')
Output
<Employee John Doe> Age: 32 Active: True ----- <Employee Jane Tanaka> Age: 32 Active: False -----

Aqui, você vê que John e Jane são os funcionários que têm 32 anos. John está ativo e Jane está fora do escritório.

Para obter os funcionários que têm 32 anos e estão ativos, você usará duas condições com o método filter():

  • Employee.age == 32
  • Employee.active == True

Para juntar essas duas condições, use a função db.and_() assim:

  1. active_and_32 = Employee.query.filter(db.and_(Employee.age == 32,
  2. Employee.active == True)).all()
  3. print(active_and_32)
Output
[<Employee John Doe>]

Aqui, você usa a sintaxe filter(db.and_(condição1, condição2)).

O uso de all() na consulta retorna uma lista de todos os registros que correspondem às duas condições. Você pode usar o método first() para obter o primeiro resultado:

  1. active_and_32 = Employee.query.filter(db.and_(Employee.age == 32,
  2. Employee.active == True)).first()
  3. print(active_and_32)
Output
<Employee John Doe>

Para um exemplo mais complexo, você pode usar o db.and_() com a função date() para obter funcionários que foram contratados em um período de tempo específico. Neste exemplo, você obtém todos os funcionários contratados no ano de 2019:

  1. from datetime import date
  2. hired_in_2019 = Employee.query.filter(db.and_(Employee.hire_date >= date(year=2019, month=1, day=1), Employee.hire_date < date(year=2020, month=1, day=1))).all()
  3. for employee in hired_in_2019:
  4. print(employee, ' | Hired: ', employee.hire_date)
Output
<Employee Alex Brown> | Hired: 2019-01-03 <Employee Emily Vill> | Hired: 2019-06-09

Aqui você importa a função date() e filtra os resultados usando a função db.and_() para combinar as duas seguintes condições:

  • Employee.hire_date >= date(year=2019, month=1, day=1): Isso é True para funcionários contratados no primeiro de janeiro de 2019 ou posteriormente.
  • Employee.hire_date < date(year=2020, month=1, day=1): Isso é Verdadeiro para funcionários contratados antes do primeiro de janeiro de 2020.

Combinar as duas condições busca funcionários contratados a partir do primeiro dia de 2019 e antes do primeiro dia de 2020.

Ou

Semelhante ao db.and_(), a função db.or_() combina duas condições e se comporta como o operador or em Python. Ele busca todos os registros que atendem a uma das duas condições. Por exemplo, para obter funcionários com 32 anos ou 52, você pode combinar duas condições com a função db.or_() da seguinte forma:

  1. employees_32_or_52 = Employee.query.filter(db.or_(Employee.age == 32, Employee.age == 52)).all()
  2. for e in employees_32_or_52:
  3. print(e, '| Age:', e.age)
Output
<Employee John Doe> | Age: 32 <Employee Jane Tanaka> | Age: 32 <Employee Harold Ishida> | Age: 52

Você também pode usar os métodos startswith() e endswith() em valores de string nas condições que você passa para o método filter(). Por exemplo, para obter todos os funcionários cujo primeiro nome começa com a string 'M' e aqueles com um sobrenome que termina com a string 'e':

  1. employees = Employee.query.filter(db.or_(Employee.firstname.startswith('M'), Employee.lastname.endswith('e'))).all()
  2. for e in employees:
  3. print(e)
Output
<Employee John Doe> <Employee Mary Doe> <Employee James White> <Employee Mary Park>

Aqui você combina as seguintes duas condições:

  • Employee.firstname.startswith('M'): Corresponde a funcionários com um primeiro nome que começa com 'M'.
  • Employee.lastname.endswith('e'): Corresponde a funcionários com um sobrenome que termina com 'e'.

Agora você pode filtrar os resultados da consulta usando condições lógicas em suas aplicações Flask-SQLAlchemy. Em seguida, você vai ordenar, limitar e contar os resultados que você obtém do banco de dados.

Passo 4 — Ordenando, Limitando e Contando Resultados

Nas aplicações web, frequentemente é necessário ordenar os registros ao exibi-los. Por exemplo, você pode ter uma página para exibir as contratações mais recentes em cada departamento para informar o restante da equipe sobre as novas contratações, ou pode ordenar os funcionários exibindo os mais antigos primeiro para reconhecer os funcionários com longa permanência na empresa. Você também precisará limitar seus resultados em alguns casos, como exibir apenas as três contratações mais recentes em uma barra lateral pequena. E frequentemente é necessário contar os resultados de uma consulta, por exemplo, para exibir o número de funcionários que estão atualmente ativos. Neste passo, você aprenderá como ordenar, limitar e contar resultados.

Ordenando Resultados

Para ordenar resultados usando os valores de uma coluna específica, use o método order_by(). Por exemplo, para ordenar os resultados pelo primeiro nome dos funcionários:

  1. employees = Employee.query.order_by(Employee.firstname).all()
  2. print(employees)
Output
[<Employee Alex Brown>, <Employee Emily Vill>, <Employee Harold Ishida>, <Employee James White>, <Employee Jane Tanaka>, <Employee John Doe>, <Employee Mary Doe>, <Employee Mary Park>, <Employee Scarlett Winter>]

Conforme a saída mostra, os resultados são ordenados alfabeticamente pelo primeiro nome do funcionário.

Você pode ordenar por outras colunas. Por exemplo, pode usar o sobrenome para ordenar os funcionários:

  1. employees = Employee.query.order_by(Employee.lastname).all()
  2. print(employees)
Output
[<Employee Alex Brown>, <Employee John Doe>, <Employee Mary Doe>, <Employee Harold Ishida>, <Employee Mary Park>, <Employee Jane Tanaka>, <Employee Emily Vill>, <Employee James White>, <Employee Scarlett Winter>]

Você também pode ordenar os funcionários pela data de contratação:

  1. em_ordered_by_hire_date = Employee.query.order_by(Employee.hire_date).all()
  2. for employee in em_ordered_by_hire_date:
  3. print(employee.firstname, employee.lastname, employee.hire_date)
Output
Harold Ishida 2002-03-06 John Doe 2012-03-03 Jane Tanaka 2015-09-12 Mary Doe 2016-06-07 Alex Brown 2019-01-03 Emily Vill 2019-06-09 James White 2021-02-04 Scarlett Winter 2021-04-07 Mary Park 2021-08-11

Como mostra a saída, isso ordena os resultados desde a contratação mais antiga até a mais recente. Para reverter a ordem e torná-la descendente da contratação mais recente para a mais antiga, use o método desc() assim:

  1. em_ordered_by_hire_date_desc = Employee.query.order_by(Employee.hire_date.desc()).all()
  2. for employee in em_ordered_by_hire_date_desc:
  3. print(employee.firstname, employee.lastname, employee.hire_date)
Output
Mary Park 2021-08-11 Scarlett Winter 2021-04-07 James White 2021-02-04 Emily Vill 2019-06-09 Alex Brown 2019-01-03 Mary Doe 2016-06-07 Jane Tanaka 2015-09-12 John Doe 2012-03-03 Harold Ishida 2002-03-06

Você também pode combinar o método order_by() com o método filter() para ordenar resultados filtrados. O exemplo a seguir obtém todos os funcionários contratados em 2021 e os ordena por idade:

  1. from datetime import date
  2. hired_in_2021 = Employee.query.filter(db.and_(Employee.hire_date >= date(year=2021, month=1, day=1), Employee.hire_date < date(year=2022, month=1, day=1))).order_by(Employee.age).all()
  3. for employee in hired_in_2021:
  4. print(employee.firstname, employee.lastname,
  5. employee.hire_date, '| Age', employee.age)
Output
Scarlett Winter 2021-04-07 | Age 22 James White 2021-02-04 | Age 24 Mary Park 2021-08-11 | Age 30

Aqui, você utiliza a função db.and_() com duas condições: Employee.hire_date >= date(year=2021, month=1, day=1) para funcionários contratados no primeiro dia de 2021 ou posteriormente, e Employee.hire_date < date(year=2022, month=1, day=1) para funcionários contratados antes do primeiro dia de 2022. Em seguida, você usa o método order_by() para ordenar os funcionários resultantes por idade.

Limitando Resultados

Na maioria dos casos do mundo real, ao consultar uma tabela de banco de dados, você pode obter até milhões de resultados correspondentes, e às vezes é necessário limitar os resultados a um determinado número. Para limitar resultados no Flask-SQLAlchemy, você pode usar o método limit(). O exemplo a seguir consulta a tabela employee e retorna apenas os três primeiros resultados correspondentes:

  1. employees = Employee.query.limit(3).all()
  2. print(employees)
Output
[<Employee John Doe>, <Employee Mary Doe>, <Employee Jane Tanaka>]

Você pode usar limit() com outros métodos, como filter e order_by. Por exemplo, você pode obter os dois últimos funcionários contratados em 2021 usando o método limit() assim:

  1. from datetime import date
  2. hired_in_2021 = Employee.query.filter(db.and_(Employee.hire_date >= date(year=2021, month=1, day=1), Employee.hire_date < date(year=2022, month=1, day=1))).order_by(Employee.age).limit(2).all()
  3. for employee in hired_in_2021:
  4. print(employee.firstname, employee.lastname,
  5. employee.hire_date, '| Age', employee.age)
Output
Scarlett Winter 2021-04-07 | Age 22 James White 2021-02-04 | Age 24

Aqui, você usa a mesma consulta da seção anterior com uma chamada de método adicional limit(2).

Contagem de Resultados

Para contar o número de resultados de uma consulta, você pode usar o método count(). Por exemplo, para obter o número de funcionários atualmente no banco de dados:

  1. employee_count = Employee.query.count()
  2. print(employee_count)
Output
9

Você pode combinar o método count() com outros métodos de consulta semelhantes ao limit(). Por exemplo, para obter o número de funcionários contratados em 2021:

  1. from datetime import date
  2. hired_in_2021_count = Employee.query.filter(db.and_(Employee.hire_date >= date(year=2021, month=1, day=1), Employee.hire_date < date(year=2022, month=1, day=1))).order_by(Employee.age).count()
  3. print(hired_in_2021_count)
Output
3

Aqui você usa a mesma consulta que usou anteriormente para obter todos os funcionários contratados em 2021. E você usa o count() para recuperar o número de entradas, que é 3.

Você ordenou, limitou e contou os resultados da consulta no Flask-SQLAlchemy. Em seguida, você aprenderá como dividir os resultados da consulta em várias páginas e como criar um sistema de paginação em suas aplicações Flask.

Passo 5 — Exibindo Listas de Registros Longos em Múltiplas Páginas

Neste passo, você modificará a rota principal para fazer a página de índice exibir funcionários em várias páginas para facilitar a navegação na lista de funcionários.

Primeiro, você usará o shell do Flask para ver uma demonstração de como usar o recurso de paginação no Flask-SQLAlchemy. Abra o shell do Flask se ainda não o tiver feito:

  1. flask shell

Digamos que você queira dividir os registros de funcionários na sua tabela em várias páginas, com dois itens por página. Você pode fazer isso usando o método de consulta paginate() da seguinte maneira:

  1. page1 = Employee.query.paginate(page=1, per_page=2)
  2. print(page1)
  3. print(page1.items)
Output
<flask_sqlalchemy.Pagination object at 0x7f1dbee7af80> [<Employee John Doe>, <Employee Mary Doe>]

Você usa o parâmetro page do método de consulta paginate() para especificar a página que deseja acessar, que é a primeira página neste caso. O parâmetro per_page especifica o número de itens que cada página deve ter. Neste caso, você o define como 2 para fazer com que cada página tenha dois itens.

A variável page1 aqui é um objeto de paginação, que dá acesso a atributos e métodos que você usará para gerenciar sua paginação.

Você acessa os itens da página usando o atributo items.

Para acessar a próxima página, você pode usar o método next() do objeto de paginação da seguinte maneira, o resultado retornado também é um objeto de paginação:

  1. page2 = page1.next()
  2. print(page2.items)
  3. print(page2)
Output
[<Employee Jane Tanaka>, <Employee Alex Brown>] <flask_sqlalchemy.Pagination object at 0x7f1dbee799c0>

Você pode obter um objeto de paginação para a página anterior usando o método prev(). No exemplo a seguir, você acessa o objeto de paginação para a quarta página e, em seguida, acessa o objeto de paginação de sua página anterior, que é a página 3:

  1. page4 = Employee.query.paginate(page=4, per_page=2)
  2. print(page4.items)
  3. page3 = page4.prev()
  4. print(page3.items)
Output
[<Employee Scarlett Winter>, <Employee Emily Vill>] [<Employee James White>, <Employee Harold Ishida>]

Você pode acessar o número da página atual usando o atributo page da seguinte maneira:

  1. print(page1.page)
  2. print(page2.page)
Output
1 2

Para obter o número total de páginas, utilize o atributo pages do objeto de paginação. No exemplo a seguir, tanto page1.pages quanto page2.pages retornam o mesmo valor porque o número total de páginas é uma constante:

  1. print(page1.pages)
  2. print(page2.pages)
Output
5 5

Para o número total de itens, utilize o atributo total do objeto de paginação:

  1. print(page1.total)
  2. print(page2.total)
Output
9 9

Aqui, como você consulta todos os funcionários, o número total de itens na paginação é 9, porque há nove funcionários no banco de dados.

A seguir estão alguns dos outros atributos que os objetos de paginação possuem:

  • prev_num: O número da página anterior.
  • next_num: O número da próxima página.
  • has_next: True se houver uma próxima página.
  • has_prev: True se houver uma página anterior.
  • per_page: O número de itens por página.

O objeto de paginação também possui um método iter_pages() que você pode percorrer para acessar números de página. Por exemplo, você pode imprimir todos os números de página assim:

  1. pagination = Employee.query.paginate(page=1, per_page=2)
  2. for page_num in pagination.iter_pages():
  3. print(page_num)
Output
1 2 3 4 5

O seguinte é uma demonstração de como acessar todas as páginas e seus itens usando um objeto de paginação e o método iter_pages():

  1. pagination = Employee.query.paginate(page=1, per_page=2)
  2. for page_num in pagination.iter_pages():
  3. print('PAGE', pagination.page)
  4. print('-')
  5. print(pagination.items)
  6. print('-'*20)
  7. pagination = pagination.next()
Output
PAGE 1 - [<Employee John Doe>, <Employee Mary Doe>] -------------------- PAGE 2 - [<Employee Jane Tanaka>, <Employee Alex Brown>] -------------------- PAGE 3 - [<Employee James White>, <Employee Harold Ishida>] -------------------- PAGE 4 - [<Employee Scarlett Winter>, <Employee Emily Vill>] -------------------- PAGE 5 - [<Employee Mary Park>] --------------------

Aqui, você cria um objeto de paginação que começa da primeira página. Você percorre as páginas usando um laço for com o método de paginação iter_pages(). Você imprime o número da página e os itens da página, e define o objeto pagination como o objeto de paginação de sua próxima página usando o método next().

Você também pode usar os métodos filter() e order_by() com o método paginate() para paginar resultados de consulta filtrados e ordenados. Por exemplo, você pode obter funcionários com mais de trinta anos e ordenar os resultados por idade e paginar os resultados assim:

  1. pagination = Employee.query.filter(Employee.age > 30).order_by(Employee.age).paginate(page=1, per_page=2)
  2. for page_num in pagination.iter_pages():
  3. print('PAGE', pagination.page)
  4. print('-')
  5. for employee in pagination.items:
  6. print(employee, '| Age: ', employee.age)
  7. print('-'*20)
  8. pagination = pagination.next()
Output
PAGE 1 - <Employee John Doe> | Age: 32 <Employee Jane Tanaka> | Age: 32 -------------------- PAGE 2 - <Employee Mary Doe> | Age: 38 <Employee Harold Ishida> | Age: 52 --------------------

Agora que você tem uma compreensão sólida de como a paginação funciona no Flask-SQLAlchemy, você vai editar a página de índice da sua aplicação para exibir funcionários em várias páginas para uma navegação mais fácil.

Saia do shell do Flask:

  1. exit()

Para acessar páginas diferentes, você usará parâmetros de URL, também conhecidos como cadeias de consulta de URL, que são uma maneira de passar informações para a aplicação através da URL. Os parâmetros são passados para a aplicação na URL após um símbolo ?. Por exemplo, para passar um parâmetro page com valores diferentes, você pode usar as seguintes URLs:

http://127.0.0.1:5000/?page=1
http://127.0.0.1:5000/?page=3

Aqui, a primeira URL passa o valor 1 para o parâmetro de URL page. A segunda URL passa o valor 3 para o mesmo parâmetro.

Abra o arquivo app.py:

  1. nano app.py

Edite a rota do índice para ficar como segue:

@app.route('/')
def index():
    page = request.args.get('page', 1, type=int)
    pagination = Employee.query.order_by(Employee.firstname).paginate(
        page, per_page=2)
    return render_template('index.html', pagination=pagination)

Aqui, você obtém o valor do parâmetro de URL page usando o objeto request.args e seu método get(). Por exemplo, /?page=1 obterá o valor 1 do parâmetro de URL page. Você passa 1 como valor padrão e passa o tipo Python int como argumento para o parâmetro type para garantir que o valor seja um número inteiro.

A seguir, você cria um objeto pagination, ordenando os resultados da consulta pelo primeiro nome. Você passa o valor do parâmetro de URL page para o método paginate(), e divide os resultados em dois itens por página passando o valor 2 para o parâmetro per_page.

Por último, você passa o objeto pagination que construiu para o modelo index.html renderizado.

Salve e feche o arquivo.

Em seguida, edite o modelo index.html para exibir os itens de paginação:

  1. nano templates/index.html

Altere a tag div de conteúdo adicionando um cabeçalho h2 que indica a página atual, e altere o loop for para iterar sobre o objeto pagination.items em vez do objeto employees, que não está mais disponível:

<div class="content">
    <h2>(Page {{ pagination.page }})</h2>
    {% for employee in pagination.items %}
        <div class="employee">
            <p><b>#{{ employee.id }}</b></p>
            <b>
                <p class="name">{{ employee.firstname }} {{ employee.lastname }}</p>
            </b>
            <p>{{ employee.email }}</p>
            <p>{{ employee.age }} years old.</p>
            <p>Hired: {{ employee.hire_date }}</p>
            {% if employee.active %}
                <p><i>(Active)</i></p>
            {% else %}
                <p><i>(Out of Office)</i></p>
            {% endif %}
        </div>
    {% endfor %}
</div>

Salve e feche o arquivo.

Se você ainda não o fez, defina as variáveis de ambiente FLASK_APP e FLASK_ENV e execute o servidor de desenvolvimento:

  1. export FLASK_APP=app
  2. export FLASK_ENV=development
  3. flask run

Agora, navegue até a página de índice com diferentes valores para o parâmetro de URL page:

http://127.0.0.1:5000/
http://127.0.0.1:5000/?page=2
http://127.0.0.1:5000/?page=4
http://127.0.0.1:5000/?page=19

Você verá diferentes páginas com dois itens cada, e diferentes itens em cada página, como você já viu anteriormente no shell do Flask.

Se o número da página fornecido não existir, você receberá um erro HTTP 404 Not Found, o que é o caso do último URL na lista de URLs anterior.

Em seguida, você criará um widget de paginação para navegar entre páginas, você usará alguns atributos e métodos do objeto de paginação para exibir todos os números de página, cada número será vinculado à sua página dedicada, e um botão <<< para retroceder se a página atual tiver uma página anterior, e um botão >>> para ir para a próxima página se ela existir.

O widget de paginação ficará assim:


Para adicioná-lo, abra index.html:

  1. nano templates/index.html

Edite o arquivo adicionando a seguinte div destacada abaixo da div de conteúdo:

flask_app/templates/index.html
<div class="content">
    {% for employee in pagination.items %}
        <div class="employee">
            <p><b>#{{ employee.id }}</b></p>
            <b>
                <p class="name">{{ employee.firstname }} {{ employee.lastname }}</p>
            </b>
            <p>{{ employee.email }}</p>
            <p>{{ employee.age }} years old.</p>
            <p>Hired: {{ employee.hire_date }}</p>
            {% if employee.active %}
                <p><i>(Active)</i></p>
            {% else %}
                <p><i>(Out of Office)</i></p>
            {% endif %}
        </div>
    {% endfor %}
</div>

<div class="pagination">
    {% if pagination.has_prev %}
        <span>
            <a class='page-number' href="{{ url_for('index', page=pagination.prev_num) }}">
                {{ '<<<' }}
            </a>
        </span>
    {% endif %}

    {% for number in pagination.iter_pages() %}
        {% if pagination.page != number %}
            <span>
                    <a class='page-number'
                        href="{{ url_for('index', page=number) }}">
                    {{ number }}
                    </a>
            </span>
        {% else %}
            <span class='current-page-number'>{{ number }}</span>
        {% endif %}
    {% endfor %}

    {% if pagination.has_next %}
        <span>
            <a class='page-number'
                href="{{ url_for('index', page=pagination.next_num) }}">
                {{ '>>>' }}
            </a>
        </span>
    {% endif %}
</div>

Salve e feche o arquivo.

Aqui, você utiliza a condição if pagination.has_prev para adicionar um link <<< para a página anterior se a página atual não for a primeira. Você vincula à página anterior usando a chamada de função url_for('index', page=pagination.prev_num), na qual você vincula à função de visualização de índice, passando o valor pagination.prev_num para o parâmetro de URL page.

Para exibir links para todos os números de página disponíveis, você itera pelos itens do método pagination.iter_pages(), que fornece um número de página em cada iteração.

Você usa a condição if pagination.page != número para verificar se o número da página atual não é o mesmo que o número no loop atual. Se a condição for verdadeira, você vincula à página para permitir que o usuário altere a página atual para outra página. Caso contrário, se a página atual for a mesma que o número do loop, você exibe o número sem um link. Isso permite que os usuários saibam o número da página atual no widget de paginação.

Por último, você usa a condição pagination.has_next para verificar se a página atual tem uma próxima página, caso em que você vincula a ela usando a chamada url_for('index', page=pagination.next_num) e um link >>>.

Navegue até a página de índice em seu navegador: http://127.0.0.1:5000/

Você verá que o widget de paginação está totalmente funcional:


Aqui, você usa >>> para mover para a próxima página e <<< para a página anterior, mas também pode usar quaisquer outros caracteres que desejar, como > e < ou imagens em tags <img>.

Você exibiu funcionários em várias páginas e aprendeu como lidar com a paginação no Flask-SQLAlchemy. E agora você pode usar seu widget de paginação em outros aplicativos Flask que você construir.

Conclusão

Você utilizou o Flask-SQLAlchemy para criar um sistema de gerenciamento de funcionários. Você consultou uma tabela e filtrou os resultados com base nos valores das colunas e em condições lógicas simples e complexas. Você ordenou, contou e limitou os resultados da consulta. E criou um sistema de paginação para exibir um certo número de registros em cada página em sua aplicação web e navegar entre as páginas.

Você pode utilizar o que aprendeu neste tutorial em combinação com os conceitos explicados em alguns dos nossos outros tutoriais do Flask-SQLAlchemy para adicionar mais funcionalidades ao seu sistema de gerenciamento de funcionários:

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

Source:
https://www.digitalocean.com/community/tutorials/how-to-query-tables-and-paginate-data-in-flask-sqlalchemy