No mundo do desenvolvimento web, a criação de aplicações CRUD (Create, Read, Update, Delete) é uma tarefa comum. Essas aplicações permitem que os usuários interajam com bancos de dados de forma simples e eficiente. Neste artigo, vamos explorar como criar um CRUD completo usando FastHTML e Python. O código apresentado é altamente eficiente, modular e fácil de manter, atendendo às melhores práticas de desenvolvimento.
O que é FastHTML?
Em primeiro lugar, FastHTML é uma biblioteca Python que facilita a criação de interfaces web dinâmicas, responsivas e a criação de sua biblioteca de componentes. Além disso, ele combina a simplicidade do HTML com a potência do Python, o que permite que desenvolvedores criem aplicações web de maneira rápida e eficiente. No nosso exemplo, usamos FastHTML para criar um CRUD que gerencia uma tabela de pessoas, incluindo funcionalidades como adicionar, editar, excluir e listar registros. Como resultado, neste projeto, temos o código 100% em Python, o que demonstra a versatilidade e a praticidade dessa biblioteca para o desenvolvimento web.
Estrutura do Projeto
O projeto é organizado em módulos, o que facilita a manutenção e a escalabilidade. Aqui está uma visão geral da estrutura:
- main.py: O ponto de entrada da aplicação, onde configuramos o FastHTML e registramos as rotas.
- constantes.py: Contém constantes como o número de registros por página e expressões regulares para validação.
- SGBD.py: Gerencia a conexão com o banco de dados.
- componentes.py: Define componentes reutilizáveis, como a função caixa_mensagem.
- classes.py: Define a classe Pessoa, que representa a entidade no banco de dados.
Funcionalidades do CRUD
- Adicionar Registros
A função adiciona_pessoa permite que os usuários adicionem novos registros à tabela. Antes de inserir os dados, o sistema valida o campo nome para garantir que ele não esteja vazio, não contenha números ou caracteres especiais. Se a validação falhar, uma mensagem de erro é exibida.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@rt("/adiciona/pessoa") def adiciona_pessoa(nome: str): try: if validar_formulario(nome): db_pessoa.insert(nome=nome) return Div( listar_pessoas(page=1), caixa_mensagem("sucesso","Pessoa adicionada com sucesso!"), limpar_formulario() ) except ValueError as e: return Div( listar_pessoas(page=1), caixa_mensagem("erro", str(e)), limpar_formulario() ) |
- Editar Registros
A função editar_pessoa permite que os usuários editem registros existentes. O sistema redireciona o usuário para o formulário de edição, onde ele pode alterar o nome da pessoa. Após a edição, o sistema valida os dados e, se tudo estiver correto, atualiza o registro no banco de dados.
1 2 3 4 5 6 |
@rt("/editar/pessoa/{id}") def editar_pessoa(id: int, page: int = 1): pessoa = db_pessoa.get(id) if not pessoa: return caixa_mensagem("erro", "Pessoa não encontrada!") return Redirect(f"/frm/pessoa?edit_id={id}&page={page}") |
- Excluir Registros
A função excluir_pessoa permite que os usuários excluam registros da tabela. O sistema remove o registro do banco de dados e atualiza a listagem, mantendo a paginação correta.
1 2 3 4 5 6 7 8 9 10 11 |
@rt("/excluir/pessoa/{id}") def excluir_pessoa(id: int, page: int = 1): db_pessoa.delete(id) total_pessoas = len(db_pessoa()) total_paginas = (total_pessoas + NUMERO_REGISTROS_POR_PAGINA - 1) // NUMERO_REGISTROS_POR_PAGINA if page > total_paginas and page > 1: page -= 1 return Div( listar_pessoas(page=page), caixa_mensagem("sucesso", "✖ Pessoa removida com sucesso!") ) |
- Listar Registros com Paginação
A função listar_pessoas exibe os registros da tabela com paginação. Os usuários podem navegar entre as páginas usando os botões “Anterior”, “Próxima”, “Primeira” e “Última”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
@rt("/listar/pessoas") def listar_pessoas(page: int = 1): total_pessoas = len(db_pessoa()) total_paginas = (total_pessoas + NUMERO_REGISTROS_POR_PAGINA - 1) // NUMERO_REGISTROS_POR_PAGINA inicio = (page - 1) * NUMERO_REGISTROS_POR_PAGINA pessoas = db_pessoa()[inicio:inicio + NUMERO_REGISTROS_POR_PAGINA] tabela = Table( Tr(Th("Id"), Th("Nome"), Th("Ações")), *[ Tr( Td(pessoa.id), Td(pessoa.nome), Td( Button("✏️ Editar", hx_get=f"/editar/pessoa/{pessoa.id}?page={page}", hx_target="#listagem", hx_swap="innerHTML", style="background:#134B70; color:white; border:none; padding:5px 8px; cursor:pointer;"), Button("✖ Excluir", hx_get=f"/excluir/pessoa/{pessoa.id}?page={page}", hx_target="#listagem", hx_swap="innerHTML", style="margin-left:10px; background:#A0153E; color:white; border:none; padding:5px 8px; cursor:pointer;") ) ) for pessoa in pessoas ] ) paginacao = Div( A("⏮️", title="Primeira Página", hx_get=f"/listar/pessoas?page=1", hx_target="#listagem", style="font-size: 30px; margin-right: 10px;" if page > 1 else "display:none;"), A("◀️", title="Anterior", hx_get=f"/listar/pessoas?page={page-1}", hx_target="#listagem", style="font-size: 30px; margin-right: 10px;" if page > 1 else "display:none;"), Label(f" {page} ", style="font-size: 30px; color: blue"), A("▶️", title="Próxima", hx_get=f"/listar/pessoas?page={page+1}", hx_target="#listagem", style="font-size: 30px; margin-left: 10px;" if page < total_paginas else "display:none;"), A("⏩", title="Última Página", hx_get=f"/listar/pessoas?page={total_paginas}", hx_target="#listagem", style="font-size: 30px; margin-left: 10px;" if page < total_paginas else "display:none;"), style="margin-top: 20px; display: flex; gap: 10px;" ) return Div( tabela, paginacao, limpar_formulario() ) |
- Validação de Dados
A função validar_formulario é usada para garantir que os dados inseridos pelos usuários sejam válidos. Ela verifica se o campo nome não está vazio, não contém números ou caracteres especiais.
1 2 3 4 5 6 7 8 9 10 11 12 |
def validar_formulario(nome): valido = True if not nome: valido = False raise ValueError("O campo 'nome' é obrigatório") if re.search(REGEX_VALIDAR["tem_numeros"], nome): valido = False raise ValueError("O campo 'nome' não pode ter números.") if re.search(REGEX_VALIDAR["tem_caracteres_especiais"], nome): valido = False raise ValueError("O campo 'nome' não pode ter caracteres especiais.") return valido |
Eficiência e Boas Práticas
Primeiramente, o código foi desenvolvido seguindo as melhores práticas de desenvolvimento, como modularização, validação de dados e paginação. Dessa forma, isso garante que a aplicação seja não apenas eficiente, mas também fácil de manter e altamente escalável. Além disso, o uso do FastHTML permite uma integração perfeita entre o front-end e o back-end, o que, por sua vez, proporciona uma experiência de usuário fluida e intuitiva. Portanto, ao adotar essas práticas e ferramentas, o desenvolvimento se torna mais organizado e o resultado final, significativamente mais robusto.
Integrando varios formulários ao main.py
O código principal do projeto fica em main.py e cada formulário em um arquivo python separado, com suas rotas e sua validação especifica. Veja como integrar os formulários em main.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from fasthtml.common import fast_app, serve from SGBD import get_db from frm_pessoa import frm_pessoa, adiciona_pessoa, editar_pessoa, salvar_pessoa, excluir_pessoa, listar_pessoas # Configuração do FastHTML app, rt = fast_app() db = get_db() # Pessoa rt("/frm/pessoa")(frm_pessoa) rt("/adiciona/pessoa")(adiciona_pessoa) rt("/editar/pessoa/{id}")(editar_pessoa) rt("/salvar/pessoa/{id}")(salvar_pessoa) rt("/excluir/pessoa/{id}")(excluir_pessoa) rt("/listar/pessoas")(listar_pessoas) # Servir a aplicação serve() |
Conclusão
Em resumo, este guia mostrou como o FastHTML pode simplificar a criação de CRUDs em Python. Ao seguir os passos apresentados, você estará apto a desenvolver aplicações web eficientes e de alta qualidade. Portanto, não hesite em experimentar o FastHTML em seus projetos. Por fim, se você gostou deste conteúdo, compartilhe com outros desenvolvedores e deixe seu feedback nos comentários. Dessa forma, podemos continuar trazendo mais tutoriais como este!
Formulário
Chamada para Ação
Se você gostou deste artigo e quer aprender mais sobre desenvolvimento web com Python, siga-nos nas redes sociais e divulgue nosso site. Também deixe o comentário para identificarmos o próximo post.