Flask SQLAlchemy: Koneksi Database dan Model
List Python hanya hidup selama proses aplikasi berjalan. Begitu server dimatikan atau restart, semua data di dalam list ikut hilang. Database memberi tempat penyimpanan yang bertahan di luar proses Flask, sehingga note yang dibuat hari ini masih bisa dibaca ketika aplikasi dijalankan kembali.
Kita akan memakai SQLite dan Flask-SQLAlchemy. SQLite tidak membutuhkan server database terpisah, sedangkan Flask-SQLAlchemy membantu menghubungkan lifecycle Flask dengan SQLAlchemy.
Install Extension Database
Aktifkan virtual environment project, lalu install package-nya:
python -m pip install flask-sqlalchemy
Package ini menambahkan integrasi Flask, tetapi konsep utamanya tetap berasal dari SQLAlchemy: tabel direpresentasikan sebagai class, row menjadi object, dan operasi database dilakukan melalui session.
Definisikan Model Note
Buat file models.py agar object database dan model tidak menumpuk di file aplikasi:
# File: models.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
def __repr__(self):
return f"<Note {self.id}: {self.title}>"
Class Note akan dipetakan ke tabel note. Setiap instance mewakili satu row. Field id menjadi primary key yang membedakan setiap note, sedangkan title dibatasi sampai 120 karakter dan tidak boleh bernilai NULL.
nullable=False adalah aturan di level database, bukan pengganti validasi form. Input string kosong seperti "" tetap bukan NULL, jadi route masih perlu memastikan judul benar-benar berisi teks.
Sambungkan SQLAlchemy ke Flask
Application factory menentukan lokasi database dan memanggil db.init_app(app):
# File: app.py
from flask import Flask
from models import Note, db
def create_app():
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
db.init_app(app)
return app
URI sqlite:///app.db meminta Flask-SQLAlchemy memakai file SQLite bernama app.db. Untuk URI relatif seperti ini, file biasanya dibuat di folder instance/ milik aplikasi, bukan selalu tepat di sebelah app.py.
Object db dibuat tanpa mengikatnya ke satu aplikasi tertentu. Baru di dalam create_app(), db.init_app(app) menghubungkan extension ke instance Flask. Pola ini membuat config testing atau database lain lebih mudah dipasang tanpa menulis ulang model.
Import Note memastikan model sudah dikenal sebelum tabel dibuat. Walaupun nama Note tidak dipakai langsung di app.py, import tersebut memuat definisi model ke metadata SQLAlchemy.
Buat Tabel untuk Pertama Kali
Model baru hanya mendeskripsikan tabel; file database belum otomatis memiliki tabel tersebut. Buka Flask shell:
# File: terminal
python -m flask --app app shell
Lalu jalankan:
# File: Flask shell
from models import db
db.create_all()
exit()
db.create_all() cocok untuk latihan dan pembuatan tabel awal. Ia tidak dirancang untuk mengubah struktur tabel yang sudah ada. Ketika project mulai berkembang, gunakan migration tool seperti Flask-Migrate agar perubahan kolom tercatat dan bisa dijalankan secara bertahap.
Simpan dan Baca Data
Supaya proses session terlihat tanpa form, buat script kecil berikut:
# File: seed.py
from app import create_app
from models import Note, db
app = create_app()
with app.app_context():
note = Note(title="Belajar Flask-SQLAlchemy")
db.session.add(note)
db.session.commit()
notes = db.session.execute(db.select(Note)).scalars().all()
for item in notes:
print(item.id, item.title)
Jalankan dengan python seed.py. Block app.app_context() memberi tahu Flask instance aplikasi mana yang sedang digunakan, sehingga SQLAlchemy bisa membaca config database yang benar.
db.session.add(note) memasukkan object ke unit kerja session, tetapi perubahan belum permanen. db.session.commit() menyelesaikan transaksi dan menuliskannya ke database. Setelah commit, note.id sudah diisi dari primary key yang dibuat SQLite.
Query db.select(Note) memilih seluruh note. Method .scalars() mengambil object Note dari hasil query, lalu .all() mengubahnya menjadi list.
Perubahan Model Perlu Migration
Kalau Kamu menambahkan field body ke class setelah tabel dibuat, db.create_all() tidak otomatis menambahkan kolom itu ke tabel lama. Ini salah satu sumber kebingungan paling umum saat mulai memakai ORM. Model Python dan struktur database adalah dua hal yang perlu dijaga tetap sinkron melalui migration.
Untuk latihan, tambahkan field body yang boleh kosong dan created_at yang memiliki nilai default. Karena project ini masih percobaan, Kamu boleh menghapus database lalu menjalankan db.create_all() lagi. Untuk data yang perlu dipertahankan, gunakan migration dan jangan menghapus database sembarangan.
Setelah script bisa dijalankan dua kali dan hasil sebelumnya masih muncul, perbedaan antara data di memory dan data persisten seharusnya mulai terasa. Berikutnya, object dan query yang sama bisa dipakai dari route untuk membangun alur CRUD.
Artikel Terkait
Lanjutkan membaca topik yang masih satu konteks.
Flask Authentication: Login, Session, dan Logout
Buat authentication Flask dengan password hash, login session, current user, protected route, dan logout tanpa menyimpan password mentah.
Flask CRUD SQLAlchemy: Create, Read, Update, Delete
Bangun CRUD Flask dan SQLAlchemy untuk membuat, membaca, mengubah, serta menghapus note lengkap dengan validasi, form, dan redirect.
Struktur Project Flask: Blueprint, Template, dan Config
Rapikan struktur project Flask dengan application factory, Blueprint, folder route, template, static files, dan config yang terpisah.
Flask Static Files: CSS, JavaScript, dan Asset
Atur static files Flask untuk CSS, JavaScript, dan gambar, lalu panggil setiap asset dengan url_for agar path tetap mudah dirawat.