ДокументацияБлок 1: основы

Создание приложения для заметок с помощью Nexy, часть 3: динамические маршруты и API

Часть 3 дает каждой заметке свой собственный URL-адрес /notes/1 и обслуживает те же заметки, что и JSON в /api/notes, оба считываются из одного модуля Python.

Прежде чем начать: приложение из части 2.

Храните заметки в одном модуле

Страница и API будут читать один и тот же список. Переместите его в отдельный модуль с помощью функции, которая находит одну заметку:

src/notes.py
NOTES = {1: "Buy milk", 2: "Ship Nexy"}  def find(note_id: int) -> str | None:    return NOTES.get(note_id)

Свяжите каждую заметку с соответствующей страницей.

источник/маршруты/заметки/index.nexy
---from src.notes import NOTES notes = NOTES.items()---<section class="app-page">  <h1>Notes</h1>  <ul>    {% for id, text in notes %}    <li><a href="/notes/{{ id }}">{{ text }}</a></li>    {% endfor %}  </ul></section>
src/apps/notes/notes_view.nexy
---from src.notes import NOTES notes = NOTES.items()---<section class="app-page">  <h1>Notes</h1>  <ul>    {% for id, text in notes %}    <li><a href="/notes/{{ id }}">{{ text }}</a></li>    {% endfor %}  </ul></section>

Добавить страницу в заметку

Имя папки или файла в скобках является сегментом URL-адреса: [id].nexy отвечает на /notes/1, /notes/2 и передает сегмент на страницу в качестве реквизита. id: prop[int] преобразует его в число, поэтому /notes/abc отвечает на 404 до запуска страницы.

src/маршруты/заметки/[id].nexy
---from nexy import notFoundfrom src.notes import find id: prop[int]text = find(id)if text is None:    notFound()---<section class="app-page">  <h1>{{ text }}</h1>  <a href="/notes">All notes</a></section>

{id} в пути контроллера — это сегмент URL-адреса, передаваемый методу под этим именем. id: int преобразует его в число, поэтому /notes/abc отвечает на 404 до запуска метода.

src/apps/notes/note_view.nexy
---text: prop[str]---<section class="app-page">  <h1>{{ text }}</h1>  <a href="/notes">All notes</a></section>

notFound() останавливает запрос с помощью 404: примечание, которое не существует, отвечает как URL-адрес, который не существует.

Подавать заметки в формате JSON

Файл .py в папке src/routes/ представляет собой маршрут API. Каждая функция, названная в честь метода HTTP, отвечает этому методу:

src/routes/api/notes.py
from src.notes import NOTES  async def GET():    return [{"id": id, "text": text} for id, text in NOTES.items()]

Три контроллера заметок в одном файле. Каждый метод, названный в честь метода HTTP, отвечает этому методу:

src/apps/notes/notes_controller.py
from nexy import notFoundfrom nexy.decorators import Controllerfrom nexy.hooks import useViewsfrom src.notes import NOTES, find LAYOUT = "src/apps/layout.nexy"  def page(view: str, **context: object):    return useViews(LAYOUT, context={"children": useViews(view, context=context)})  @Controller("/notes")class NotesController:    async def get(self):        return page("src/apps/notes/notes_view.nexy")  @Controller("/notes/{id}")class NoteController:    async def get(self, id: int):        text = find(id)        if text is None:            notFound()        return page("src/apps/notes/note_view.nexy", text=text)  @Controller("/api/notes")class NotesApiController:    async def get(self) -> list[dict]:        return [{"id": id, "text": text} for id, text in NOTES.items()]
src/apps/app_module.py
from nexy.decorators import Module from .app_controller import AboutController, AppControllerfrom .notes.notes_controller import NoteController, NotesApiController, NotesController  @Module()class AppModule:    controllers = [AppController, AboutController, NotesController, NoteController, NotesApiController]

Проверьте три URL-адреса:

API вместе со схемой указан в http://localhost:3000/docs.

Что вы узнали

  • [id].nexy — динамический сегмент; id: prop[int] читает и преобразует его.
  • Файл .py под src/routes/ отвечает в формате JSON, по одной функции на каждый HTTP-метод.
  • {id} в пути контроллера — динамический сегмент; id: int преобразует его.
  • Метод контроллера, возвращающий данные, отвечает в формате JSON; тот, который возвращает useViews отвечает на страницу.
  • notFound() отвечает 404 откуда угодно; общий модуль поддерживает синхронизацию страниц и API.

Следующие шаги

Изменить на GitHub

Enter открывает результат, Esc закрывает.