الوثائقالوحدة الأولى: الأساسيات

أنشئ تطبيق ملاحظات باستخدام Nexy، الجزء 3: المسارات الديناميكية وواجهة برمجة التطبيقات

يمنح الجزء 3 كل ملاحظة عنوان URL الخاص بها، /notes/1، ويقدم نفس الملاحظات مثل JSON في /api/notes، وكلاهما يُقرأ من وحدة Python واحدة.

قبل أن تبدأ: تطبيق الجزء 2.

احتفظ بالملاحظات في وحدة واحدة

ستقرأ الصفحة وواجهة برمجة التطبيقات نفس القائمة. انقله إلى وحدة نمطية خاصة به، باستخدام وظيفة تعثر على ملاحظة واحدة:

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

ربط كل ملاحظة بصفحتها

src/routes/notes/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/routes/notes/[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 يغلق.