Pular para conteúdo

Exercícios da aula 04

Exercício 01

Fazer uma alteração no modelo (tabela User) e adicionar um campo chamado updated_at:

  • Esse campo deve ser mapeado para o tipo datetime
  • Esse campo não deve ser inicializado por padrão init=False
  • O valor padrão deve ser now
  • Toda vez que a tabela for atualizada esse campo deve ser atualizado:
    mapped_column(onupdate=func.now())
    

Solução

@table_registry.mapped_as_dataclass
class User:
    __tablename__ = 'users'

    id: Mapped[int] = mapped_column(init=False, primary_key=True)
    username: Mapped[str] = mapped_column(unique=True)
    password: Mapped[str]
    email: Mapped[str] = mapped_column(unique=True)
    created_at: Mapped[datetime] = mapped_column(
        init=False, server_default=func.now()
    )
    updated_at: Mapped[datetime] = mapped_column(  # Exercício
        init=False, server_default=func.now(), onupdate=func.now()
    )

Exercício 02

Criar uma nova migração autogerada com alembic.

Solução

Comando explicado na aula para gerar uma migração automática:

$ Execução no terminal!
alembic revision --autogenerate -m "exercicio 02 aula 04"

O Comando deve retornar algo parecido com isso:

Resultado do comando
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added column 'users.updated_at'
  Generating /home/dunossauro/git/fastapi-do-
  zero/codigo_das_aulas/04/migrations/versions/bb77f9679811_exercicio_02_aula_04.py ...  done

O arquivo de migrações deve se parecer com esse:

/migrations/versions/bb77f9679811_exercicio_02_aula_04.py
"""exercicio 02 aula 04

Revision ID: bb77f9679811
Revises: 74f39286e2f6
Create Date: ...

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'bb77f9679811'
down_revision: Union[str, None] = '74f39286e2f6'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('users', sa.Column('updated_at', sa.DateTime(), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False)) #(1)!
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('users', 'updated_at') #(2)!
    # ### end Alembic commands ###
  1. Adiciona a coluna updated_at na tabela users
  2. Remove a coluna updated_at na tabela users

Exercício 03

Aplicar essa migração ao banco de dados

Solução

Para aplicar a ultima migração devemos nos mover até a head:

$ Execução no terminal!
alembic upgrade head
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 74f39286e2f6 -> bb77f9679811, exercicio 02 aula 04

Checando o resultado no schema do banco de dados:

$ Execução no terminal!
sqlite3 database.db 
SQLite version 3.46.1 2024-08-13 09:16:08
Enter ".help" for usage hints.
sqlite> .schema
CREATE TABLE alembic_version (
        version_num VARCHAR(32) NOT NULL, 
        CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
CREATE TABLE users (
        id INTEGER NOT NULL, 
        username VARCHAR NOT NULL, 
        password VARCHAR NOT NULL, 
        email VARCHAR NOT NULL, 
        created_at DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
        updated_at DATETIME DEFAULT (CURRENT_TIMESTAMP) NOT NULL, 
        PRIMARY KEY (id), 
        UNIQUE (email), 
        UNIQUE (username)
);

Podemos ver que o campo updated_at foi criado com o tipo DATETIME e com o valor padrão para CURRENT_TIMESTAMP, assim como no created_at.