DokumentasiSatuan 2: data
Membangun aplikasi catatan dengan Nexy, bagian 5: menyimpan catatan di SQLite
Bagian 5 memindahkan catatan dari kamus Python ke dalam database SQLite, dengan model, migrasi, dan dua catatan untuk memulai, dan halaman membacanya dari sana.
Sebelum Anda memulai: aplikasi bagian 4.
Instal ORM dan alat migrasi
uv add sqlmodel alembic
SQLModel mendeskripsikan tabel sebagai kelas Python, dan Alembic mengubah perubahan pada kelas tersebut menjadi migrasi. Nexy juga tidak membungkus: Anda menggunakannya sebagaimana adanya.
Buka basis data
Alamat database ada di .env, di akar proyek. nx migrate dan aplikasi membacanya dari sana:
DATABASE_URL=sqlite:///dev.dbsqlite:///dev.db adalah file, dev.db, di sebelah nexyconfig.py: SQLite tidak memerlukan server. Jauhkan .env dari Git: Git menyimpan rahasia database sebenarnya.
Mesinnya adalah koneksi ke database. Bunyinya DATABASE_URL, dengan file yang sama sebagai default ketika variabel tidak disetel:
import os from dotenv import load_dotenvfrom sqlmodel import create_engine load_dotenv() engine = create_engine(os.getenv("DATABASE_URL", "sqlite:///dev.db"))Jelaskan sebuah catatan
from sqlmodel import Field, SQLModel class Note(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) text: strModel hidup dengan fitur yang dimilikinya, di samping pengontrolnya:
from sqlmodel import Field, SQLModel class Note(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) text: strtable=True menjadikan kelas sebagai tabel, note. id diberikan oleh database saat catatan disimpan.
Buat tabel dengan migrasi
nx migrate --initnx migrate -m "create notes"nx migrate --upgrade
--init menulis folder alembic/ dan mengarahkannya ke model Anda. -m membandingkan model dengan database dan menulis migrasi yang membuat tabel; --upgrade menjalankannya. Ubah modelnya nanti, jalankan kembali dua perintah terakhir, dan tabel akan menyusul.
Baca catatan dari database
Fungsi src/notes.py tetap menggunakan namanya, sehingga halamannya sedikit berubah: sekarang mereka membuka sesi, menanyakan tabel, dan mengembalikan objek Note alih-alih string.
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)from 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)Tambahkan dua catatan untuk memulai
Skrip awal mengisi database kosong, sehingga setiap salinan baru proyek dimulai dengan sesuatu untuk ditampilkan:
from sqlmodel import Session, select from src.configs.db import enginefrom src.models.note_model import Note def seed() -> None: with Session(engine) as session: if session.exec(select(Note)).first() is None: session.add_all([Note(text="Buy milk"), Note(text="Ship Nexy")]) session.commit() if __name__ == "__main__": seed()from sqlmodel import Session, select from src.apps.notes.note_model import Notefrom src.configs.db import engine def seed() -> None: with Session(engine) as session: if session.exec(select(Note)).first() is None: session.add_all([Note(text="Buy milk"), Note(text="Ship Nexy")]) session.commit() if __name__ == "__main__": seed()python -m src.seed
Saat startup, Nexy mengimpor setiap modul src/ untuk menemukan Tindakan bagian 6. if __name__ == "__main__": menyimpan benih untuk perintah di atas: diimpor oleh aplikasi, file hanya mendefinisikan seed, dan tidak menyentuh apa pun.
Tampilkan catatan dari database
from "@/components/NoteCard.nexy" import NoteCardfrom src.notes import all_notes notes = all_notes()<section class="app-page"> <h1>Notes</h1> {% for note in notes %} <NoteCard id="{{ note.id }}" text="{{ note.text }}" /> {% endfor %}</section>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 }}</h1> <a href="/notes">All notes</a></section>from src.notes import all_notes async def GET(): return [note.model_dump() for note in all_notes()]from "@/components/NoteCard.nexy" import NoteCardfrom src.notes import all_notes notes = all_notes()<section class="app-page"> <h1>Notes</h1> {% for note in notes %} <NoteCard id="{{ note.id }}" text="{{ note.text }}" /> {% endfor %}</section>from nexy import notFoundfrom nexy.decorators import Controllerfrom nexy.hooks import useViewsfrom src.notes import all_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): note = find(id) if note is None: notFound() return page("src/apps/notes/note_view.nexy", text=note.text) @Controller("/api/notes")class NotesApiController: async def get(self) -> list[dict]: return [note.model_dump() for note in all_notes()]Buka http://localhost:3000/notes: dua kartu yang sama, sekarang dibaca dari dev.db. Mulai ulang nexy dev, dan mereka masih di sana.
Apa yang Anda pelajari
- SQLModel mendeskripsikan tabel sebagai kelas; mesin di
src/configs/db.pymembuka database. nx migratemenulis dan menjalankan migrasi:--initsekali, lalu-mdan--upgradeper perubahan.- Halaman dan pengontrol memanggil fungsi biasa Python yang menanyakan database: Nexy tidak menambahkan lapisan.
Langkah selanjutnya
- Bagian 6: membuat catatan dari formulir
- SQLite: pragma, akses asinkron, dan pengujian pada database dalam memori