Python Pyramid

Database & Models

Konfigurasi PostgreSQL, membuat model Mahasiswa, dan menjalankan migrasi database

Konfigurasi Database PostgreSQL

Secara default, template Pyramid menggunakan SQLite. Kita akan mengubahnya untuk menggunakan PostgreSQL, yang lebih cocok untuk aplikasi production.

Pastikan PostgreSQL Sudah Terpasang

Sebelum melanjutkan, pastikan PostgreSQL sudah terinstal dan berjalan di komputer Kalian:

Verifikasi PostgreSQL
# Login ke PostgreSQL
psql -U postgres -c "SELECT version();"

# Jika berhasil, akan menampilkan versi PostgreSQL

Install PostgreSQL

Jika PostgreSQL belum terinstal:

  • Windows: Download installer dari postgresql.org
  • macOS: Gunakan Homebrew brew install postgresql atau PostgreSQL.app
  • Linux: sudo apt-get install postgresql postgresql-contrib (Ubuntu/Debian)

Membuat Database PostgreSQL

Buat database baru di PostgreSQL untuk aplikasi kita dengan izin yang lengkap:

Login ke PostgreSQL
# Login ke PostgreSQL sebagai superuser
# Ganti username dengan user PostgreSQL Kalian
psql -U postgres
Setup Database dan User
-- 1. Buat database
CREATE DATABASE pyramid_mahasiswa;

-- 2. Buat user baru
CREATE USER pyramid_user WITH ENCRYPTED PASSWORD 'pyramid_pass';

-- 3. Beri user izin ke database
GRANT ALL PRIVILEGES ON DATABASE pyramid_mahasiswa TO pyramid_user;

-- 4. Pindah ke database pyramid_mahasiswa
\c pyramid_mahasiswa

-- 5. Beri izin schema public ke user
GRANT USAGE, CREATE ON SCHEMA public TO pyramid_user;

-- 6. Ubah owner schema public (opsional tapi paling aman)
ALTER SCHEMA public OWNER TO pyramid_user;

-- 7. Pastikan owner default table/sequence future
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON TABLES TO pyramid_user;

ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON SEQUENCES TO pyramid_user;

-- 8. Keluar dari psql
\q

Penjelasan Perintah SQL

  • GRANT USAGE, CREATE: Memberikan izin untuk menggunakan dan membuat objek di schema public
  • ALTER SCHEMA OWNER: Menjadikan pyramid_user sebagai pemilik schema, memberikan kontrol penuh
  • ALTER DEFAULT PRIVILEGES: Memastikan objek yang dibuat di masa depan otomatis dimiliki pyramid_user

Password Database

Untuk production, gunakan password yang lebih kuat dan simpan dalam environment variables atau secret management system.

Install Dependensi PostgreSQL

Install psycopg2 untuk menghubungkan Python dengan PostgreSQL:

Install psycopg2
pip install psycopg2-binary

Alternatif psycopg2

Jika psycopg2-binary gagal diinstal, coba gunakan psycopg2 atau pastikan PostgreSQL development headers sudah terinstal di sistem Kalian.

Update Konfigurasi Pyramid

Ubah file development.ini untuk menggunakan PostgreSQL:

development.ini (bagian sqlalchemy.url)
# Cari dan ganti baris sqlalchemy.url
sqlalchemy.url = sqlite:///%(here)s/pyramid_mahasiswa.sqlite

# Menjadi
sqlalchemy.url = postgresql://pyramid_user:pyramid_pass@localhost:5432/pyramid_mahasiswa

Format connection string PostgreSQL:

postgresql://[user]:[password]@[host]:[port]/[database]

Troubleshooting Koneksi Database

Jika mengalami masalah koneksi database, periksa:

  • PostgreSQL service/daemon sudah berjalan
  • Username dan password yang digunakan sudah benar
  • Database pyramid_mahasiswa sudah dibuat
  • Port 5432 tidak diblokir oleh firewall
  • PostgreSQL menerima koneksi dari localhost
  • User pyramid_user memiliki izin yang cukup pada schema public

Membuat Model Mahasiswa

Sekarang kita akan membuat model untuk data Mahasiswa menggunakan SQLAlchemy ORM.

Buat File Model Mahasiswa

Buat file baru pyramid_mahasiswa/models/mahasiswa.py:

models/mahasiswa.py
from sqlalchemy import (
    Column,
    Integer,
    Text,
    Date,
)

from .meta import Base


class Mahasiswa(Base):
    """ Model untuk tabel mahasiswa """
    __tablename__ = 'mahasiswa'
    id = Column(Integer, primary_key=True)
    nim = Column(Text, unique=True, nullable=False)
    nama = Column(Text, nullable=False)
    jurusan = Column(Text, nullable=False)
    tanggal_lahir = Column(Date)
    alamat = Column(Text)

    def to_dict(self):
        return {
            'id': self.id,
            'nim': self.nim,
            'nama': self.nama,
            'jurusan': self.jurusan,
            'tanggal_lahir': self.tanggal_lahir.isoformat() if self.tanggal_lahir else None,
            'alamat': self.alamat,
        }

SQLAlchemy Column Types

Tipe kolom SQLAlchemy yang umum digunakan:

  • Integer: Bilangan bulat
  • Text: String dengan panjang tidak terbatas
  • String(length): String dengan panjang maksimal
  • Date: Tanggal (tanpa waktu)
  • DateTime: Tanggal dan waktu
  • Boolean: True/False
  • Float: Bilangan desimal

Update models/init.py

Update file pyramid_mahasiswa/models/__init__.py untuk menambahkan model Mahasiswa:

models/__init__.py
from sqlalchemy import engine_from_config
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
import zope.sqlalchemy

from .mahasiswa import Mahasiswa
from .mymodel import MyModel

configure_mappers()

def get_engine(settings, prefix='sqlalchemy.'):
    return engine_from_config(settings, prefix)

def get_session_factory(engine):
    factory = sessionmaker()
    factory.configure(bind=engine)
    return factory

def get_tm_session(session_factory, transaction_manager):
    dbsession = session_factory()
    zope.sqlalchemy.register(dbsession, transaction_manager=transaction_manager)
    return dbsession

def includeme(config):
    settings = config.get_settings()

    engine = get_engine(settings)
    session_factory = get_session_factory(engine)
    config.registry['dbsession_factory'] = session_factory

    # request.tm disediakan oleh pyramid_tm
    config.add_request_method(
        lambda request: get_tm_session(session_factory, request.tm),
        "dbsession",
        reify=True
    )

Update Script Initialize DB

Update pyramid_mahasiswa/scripts/initialize_db.py untuk menambahkan data awal:

scripts/initialize_db.py
import argparse
import sys
from datetime import date

from pyramid.paster import bootstrap, setup_logging
from sqlalchemy.exc import OperationalError

from .. import models

def setup_models(dbsession):
    """
    Add initial model objects.
    """

    existing_mahasiswa1 = dbsession.query(models.Mahasiswa).filter_by(nim='12345').first()
    existing_mahasiswa2 = dbsession.query(models.Mahasiswa).filter_by(nim='54321').first()
    
    if not existing_mahasiswa1:
        mahasiswa1 = models.Mahasiswa(
            nim='12345',
            nama='Budi Santoso',
            jurusan='Teknik Informatika',
            tanggal_lahir=date(2000, 5, 15),
            alamat='Jl. Merdeka No. 123, Bandung'
        )
        dbsession.add(mahasiswa1)
        print("Mahasiswa 12345 added.")
    else:
        print("Mahasiswa 12345 already exists.")
    
    if not existing_mahasiswa2:
        mahasiswa2 = models.Mahasiswa(
            nim='54321',
            nama='Siti Aminah',
            jurusan='Sistem Informasi',
            tanggal_lahir=date(2001, 8, 22),
            alamat='Jl. Mawar No. 45, Jakarta'
        )
        dbsession.add(mahasiswa2)
        print("Mahasiswa 54321 added.")
    else:
        print("Mahasiswa 54321 already exists.")

def parse_args(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'config_uri',
        help='Configuration file, e.g., development.ini',
    )
    return parser.parse_args(argv[1:])


def main(argv=sys.argv):
    args = parse_args(argv)
    setup_logging(args.config_uri)

    # bootstrap will return a context with request + closer
    env = bootstrap(args.config_uri)
    request = env['request']

    try:
        # gunakan request.tm (bukan tm_manager)
        with request.tm:
            dbsession = request.dbsession
            setup_models(dbsession)

        print("Database initialized successfully.")

    except OperationalError:
        print('''
Pyramid is having a problem using your SQL database.

Your database should be up and running before you
initialize your project. Make sure your database server
is running and your connection string in development.ini
is correctly configured.
''')

    finally:
        env['closer']()


if __name__ == '__main__':
    main()

SQLAlchemy ORM

SQLAlchemy Object-Relational Mapping (ORM) memungkinkan kita mendefinisikan dan bekerja dengan data seperti objek Python biasa, tanpa perlu menulis query SQL secara langsung. Setiap kelas model memetakan ke satu tabel di database.

Menjalankan Migrasi Database dengan Alembic

Alembic adalah tool migrasi database untuk SQLAlchemy. Dengan Alembic, kita dapat melacak perubahan skema database dan menerapkannya dengan mudah.

Pastikan Alembic Terpasang

Alembic sudah termasuk dalam dependensi proyek, tapi pastikan sudah terpasang:

Verifikasi Alembic
# Verifikasi Alembic sudah terpasang
pip list | grep alembic

# Jika tidak ada, install
pip install alembic

Membuat Migrasi Awal

Template Pyramid sudah menyertakan konfigurasi Alembic. Kita perlu membuat file migrasi:

Membuat File Migrasi
# Di root proyek pyramid_mahasiswa
# Pastikan virtual environment aktif

# Buat file migrasi
alembic -c development.ini revision --autogenerate -m "create mahasiswa table"

Perintah ini akan membuat file migrasi baru di folder pyramid_mahasiswa/alembic/versions/. File ini berisi kode untuk membuat tabel mahasiswa.

Autogenerate Migration

Flag --autogenerate membuat Alembic membandingkan model dengan database dan menghasilkan kode migrasi secara otomatis. Namun, selalu review file migrasi yang dihasilkan untuk memastikan kode sesuai dengan yang diharapkan.

Menjalankan Migrasi

Setelah file migrasi dibuat, kita dapat menjalankan migrasi untuk membuat tabel di database:

Menjalankan Migrasi
# Jalankan migrasi
alembic -c development.ini upgrade head

Kalian akan melihat output seperti:

INFO  [alembic.runtime.migration] Running upgrade -> 1234567890ab, create mahasiswa table

Inisialisasi Database dengan Data Awal

Sekarang kita dapat menjalankan script initialize_db.py untuk menambahkan data awal:

Inisialisasi Database
# Jalankan dari direktori root proyek
python -m pyramid_mahasiswa.scripts.initialize_db development.ini

Jika berhasil, data mahasiswa akan ditambahkan ke database.

Perintah Alembic yang Berguna

PerintahDeskripsi
alembic -c development.ini revision --autogenerate -m "message"Membuat file migrasi baru
alembic -c development.ini upgrade headMenjalankan semua migrasi yang belum dijalankan
alembic -c development.ini downgrade -1Mundur satu versi migrasi
alembic -c development.ini currentMelihat versi migrasi saat ini
alembic -c development.ini historyMelihat riwayat semua migrasi

Troubleshooting Migrasi

Jika mengalami error saat menjalankan migrasi, periksa:

  • Pastikan PostgreSQL berjalan dan dapat diakses
  • Pastikan koneksi string di development.ini sudah benar
  • Jika error menyebutkan "module not found", pastikan Kalian berada di direktori root proyek
  • Jika error terjadi saat generate revision, pastikan model Mahasiswa sudah benar dan ter-import di models/__init__.py
  • Jika terjadi error permission denied, pastikan setup database di Step 2 sudah dijalankan dengan lengkap

Verifikasi Data di Database

Untuk memverifikasi bahwa tabel dan data berhasil dibuat, Kalian bisa menggunakan psql:

Verifikasi Data
# Login ke database
psql -U pyramid_user -d pyramid_mahasiswa

# Lihat tabel yang ada
\dt

# Lihat data mahasiswa
SELECT * FROM mahasiswa;

# Keluar
\q

Kalian seharusnya melihat 2 data mahasiswa yang telah ditambahkan.

Langkah Selanjutnya

Setelah database dikonfigurasi dan model dibuat, kita akan melanjutkan ke pembuatan views dan routes untuk operasi CRUD pada bagian selanjutnya.