DocsUnidade 2: dados
Crie um aplicativo de notas com Nexy, parte 6: crie uma nota a partir de um formulário
A Parte 6 adiciona um formulário acima da lista: ele posta em uma função Python marcada como @Action, que salva a nota, e o visitante volta à lista com a nova nota nela.
Antes de começar: o aplicativo da parte 5, com seu banco de dados.
Salvar uma nota
Adicione uma função que salva uma nota e a retorna, ao lado das duas que as leem:
from sqlmodel import Session, select from src.configs.db import enginefrom src.models.note_model import Note def all_notes() -> list[Note]: with Session(engine) as session: return list(session.exec(select(Note).order_by(Note.id))) def find(note_id: int) -> Note | None: with Session(engine) as session: return session.get(Note, note_id) def add_note(text: str) -> Note: note = Note(text=text) with Session(engine) as session: session.add(note) session.commit() session.refresh(note) return notefrom sqlmodel import Session, select from src.apps.notes.note_model import Notefrom src.configs.db import engine def all_notes() -> list[Note]: with Session(engine) as session: return list(session.exec(select(Note).order_by(Note.id))) def find(note_id: int) -> Note | None: with Session(engine) as session: return session.get(Note, note_id) def add_note(text: str) -> Note: note = Note(text=text) with Session(engine) as session: session.add(note) session.commit() session.refresh(note) return noteTransforme isso em uma ação
Uma ação é uma função Python que o navegador pode chamar. @Action serve como um POST, verifica a entrada em relação às dicas de tipo e a executa:
from nexy.decorators import Actionfrom src.notes import add_note @Actionasync def create_note(text: str) -> int: return add_note(text).idNa inicialização, Nexy importa todos os módulos de src/ e serve as ações que encontra: não há rota a ser declarada, para nenhum roteador. src/actions/ é onde este tutorial os mantém.
Poste o formulário nele
Um modelo .nexy conhece o caminho de cada ação como __actions_path["name"]. Um formulário HTML simples é postado lá, para que a página funcione antes de qualquer script ser carregado:
from "@/components/NoteCard.nexy" import NoteCardfrom src.notes import all_notes notes = all_notes()<section class="app-page"> <h1>Notes</h1> <form method="post" action="{{ __actions_path['create_note'] }}"> <input name="text" placeholder="A new note" required> <button type="submit">Add</button> </form> {% for note in notes %} <NoteCard id="{{ note.id }}" text="{{ note.text }}" /> {% endfor %}</section>from "@/components/NoteCard.nexy" import NoteCardfrom src.notes import all_notes notes = all_notes()<section class="app-page"> <h1>Notes</h1> <form method="post" action="{{ __actions_path['create_note'] }}"> <input name="text" placeholder="A new note" required> <button type="submit">Add</button> </form> {% for note in notes %} <NoteCard id="{{ note.id }}" text="{{ note.text }}" /> {% endfor %}</section>A entrada é chamada text, assim como o parâmetro de create_note: é assim que o campo chega até ela.
Mostrar uma nota como texto, não como HTML
A partir de agora, uma nota é o que o visitante digitou. Um modelo .nexy escreve um valor como ele é, então uma nota <script>…</script> seria executada no navegador de todos que abrirem a lista. | e escapa: < torna-se <, e a nota aparece como texto.
id: prop[int]text: prop[str]<article class="note"> <a href="/notes/{{ id }}">{{ text | e }}</a></article> <style> .note { padding: 0.75rem 1rem; border: 1px solid #ddd; border-radius: 0.5rem; }</style>from nexy import notFoundfrom src.notes import find id: prop[int]note = find(id)if note is None: notFound()<section class="app-page"> <h1>{{ note.text | e }}</h1> <a href="/notes">All notes</a></section>text: prop[str]<section class="app-page"> <h1>{{ text | e }}</h1> <a href="/notes">All notes</a></section>Escape de todo valor proveniente de um visitante ou do banco de dados. | safe faz o oposto: guarde para o HTML que você mesmo escreveu.
Experimente
Digite Leia os documentos e pressione Adicionar. A ação salva a nota, depois responde 303 de volta para /notes, e o navegador mostra a lista novamente, com a terceira nota na parte inferior.
O que você aprendeu
@Actiontransforma uma função Python em um endpointPOST, com suas dicas de tipo como entrada.- Um formulário é postado nele através de
__actions_path["name"], sem JavaScript e retorna com303. - Os nomes dos campos do formulário são os nomes dos parâmetros da Ação.
| emostra o que um visitante digitou como texto: escape de todos os valores que não vieram de você.
Próximas etapas
- Parte 7: mostrar erros de validação
- Ações: chamadas digitadas do navegador, erros e segurança