DocsUnidad 2: datos
Cree una aplicación de notas con Nexy, parte 6: cree una nota a partir de un formulario
La parte 6 agrega un formulario encima de la lista: se publica en una función Python marcada @Action, que guarda la nota, y el visitante regresa a la lista con la nueva nota.
Antes de comenzar: la aplicación de la parte 5, con su base de datos.
guardar una nota
Agregue una función que guarde una nota y la devuelva, junto a las dos que las leen:
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 noteConviértelo en una acción
Una acción es una función Python que el navegador puede llamar. @Action lo sirve como POST, compara la entrada con las sugerencias de tipo y lo ejecuta:
from nexy.decorators import Actionfrom src.notes import add_note @Actionasync def create_note(text: str) -> int: return add_note(text).idAl inicio, Nexy importa todos los módulos de src/ y realiza las acciones que encuentra: no hay ninguna ruta que declarar, para ningún enrutador. src/actions/ es donde los guarda este tutorial.
Publica el formulario en él.
Una plantilla .nexy conoce la ruta de cada acción como __actions_path["name"]. Allí se publica un formulario HTML simple, por lo que la página funciona antes de que se cargue cualquier script:
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>La entrada se llama text, al igual que el parámetro de create_note: así llega el campo.
Mostrar una nota como texto, no como HTML
De ahora en adelante, una nota es lo que escribe un visitante. Una plantilla .nexy escribe un valor tal como está, por lo que se ejecutará una nota <script>…</script> en el navegador de todos los que abran la lista. | e se escapa: < se convierte en < y la nota se muestra 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>Escapa de cada valor que proviene de un visitante o de la base de datos. | safe hace lo contrario: guárdalo para el HTML que escribiste tú mismo.
Pruébalo
Escriba Lea los documentos y presione Agregar. La acción guarda la nota, luego responde 303 a /notes y el navegador muestra la lista nuevamente, con la tercera nota en la parte inferior.
lo que aprendiste
@Actionconvierte una función Python en un punto finalPOST, con sus sugerencias de tipo como entrada.- Se publica un formulario a través de
__actions_path["name"], sin JavaScript, y regresa con303. - Los nombres de los campos del formulario son los nombres de los parámetros de la Acción.
| emuestra lo que un visitante escribió como texto: escape todos los valores que no provengan de usted.
Próximos pasos
- Parte 7: mostrar errores de validación
- Acciones: llamadas tecleadas desde el navegador, errores y seguridad