Python İle Sqlalchemy Kütüphanesi Kullanarak Veritabanı Yönetimi Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Çalışmaya başlamadan önce sisteminizde Python 3.10 veya daha güncel bir sürümün yüklü olduğundan emin olmalısınız. SQLAlchemy, veritabanı sürücüleri ile birlikte çalışır; bu nedenle kullanacağınız veritabanı türüne göre ilgili sürücüyü de kurmanız gerekecektir. SQLite, yerleşik olduğu için ekstra bir kurulum gerektirmez ancak PostgreSQL veya MySQL kullanacaksanız ilgili sürücüleri (psycopg2 veya pymysql) kurmalısınız.

Proje dizininizde sanal bir ortam oluşturup gerekli kütüphaneyi şu komutla kurabilirsiniz:

pip install sqlalchemy

Bu komut, SQLAlchemy'nin en güncel kararlı sürümünü projenize dahil edecektir. Kurulumun başarıyla tamamlandığını doğrulamak için Python terminalinde import sqlalchemy; print(sqlalchemy.__version__) komutunu çalıştırabilirsiniz.

SQLAlchemy ile Veritabanı Bağlantısı Oluşturma

SQLAlchemy'de veritabanı bağlantısı, bir Engine (motor) nesnesi üzerinden yönetilir. Engine, veritabanı ile uygulama arasındaki köprü görevi görür ve bağlantı havuzlarını yönetir. Aşağıdaki örnekte, yerel bir SQLite veritabanına nasıl bağlanacağınızı görebilirsiniz.

from sqlalchemy import create_engine

# SQLite veritabanı bağlantı adresi (URL)
db_url = "sqlite:///kullanicilar.db"

# Engine nesnesinin oluşturulması
engine = create_engine(db_url, echo=True)

Burada echo=True parametresi, arka planda çalışan SQL sorgularını konsolda görmenizi sağlar. Bu, geliştirme aşamasında hata ayıklama (debug) için oldukça faydalıdır ancak üretim ortamında kapatılmalıdır.

Model Tanımlama ve Veri Yapısını Oluşturma

SQLAlchemy 2.0 ile birlikte gelen DeclarativeBase sınıfı, veritabanı tablolarınızı Python sınıfları olarak tanımlamanıza imkan tanır. Her sınıf bir tabloyu, sınıfın öznitelikleri ise tablonun sütunlarını temsil eder.

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column

class Base(DeclarativeBase):
    pass

class Kullanici(Base):
    __tablename__ = "kullanici_tablosu"
    
    id: Mapped[int] = mapped_column(primary_key=True)
    isim: Mapped[str] = mapped_column(nullable=False)
    email: Mapped[str] = mapped_column(unique=True)

# Tabloları veritabanında oluştur
Base.metadata.create_all(engine)

Bu kod bloğunda Mapped ve mapped_column kullanarak tip güvenli bir yapı kurduk. create_all metodu, tanımladığınız sınıflara bakarak veritabanında henüz mevcut olmayan tüm tabloları otomatik olarak oluşturur.

Session (Oturum) Yönetimi ile Veri İşleme

Veritabanına veri eklemek, güncellemek veya silmek için Session nesnesini kullanırız. Session, veritabanı işlemlerini bir "iş birimi" (Unit of Work) olarak yönetir. İşlemlerinizi tamamladığınızda commit yaparak verileri kalıcı hale getirirsiniz.

from sqlalchemy.orm import Session

# Yeni bir kullanıcı ekleme
with Session(engine) as session:
    yeni_kullanici = Kullanici(isim="Ahmet Yılmaz", email="ahmet@example.com")
    session.add(yeni_kullanici)
    session.commit()

with bloğu, işlem bittiğinde oturumun otomatik olarak kapatılmasını sağlar. Bu, bağlantı sızıntılarını önlemek için en iyi uygulamadır.

Veri Sorgulama ve Filtreleme

Veritabanından veri çekmek için select fonksiyonunu kullanırız. SQLAlchemy, karmaşık sorguları bile Pythonic bir sözdizimi ile yazmanıza olanak tanır. Aşağıdaki örnekte, belirli bir email adresine sahip kullanıcıyı nasıl sorgulayacağınızı görebilirsiniz.

from sqlalchemy import select

with Session(engine) as session:
    stmt = select(Kullanici).where(Kullanici.isim == "Ahmet Yılmaz")
    sonuc = session.scalars(stmt).first()
    
    if sonuc:
        print(f"Bulunan Kullanıcı: {sonuc.email}")

scalars(stmt) kullanımı, sorgudan dönen nesneleri doğrudan almamızı sağlar. first() metodu ise eşleşen ilk kaydı döndürür.

Güvenlik Uyarısı: SQLAlchemy, veritabanı sorgularını oluştururken otomatik olarak parametreli sorgular (parameterized queries) kullanır. Bu, SQL Injection saldırılarına karşı yerleşik bir koruma sağlar. Ancak, ham SQL sorguları yazmanız gereken durumlarda asla kullanıcıdan gelen veriyi doğrudan sorgu dizisine eklemeyin; her zaman SQLAlchemy'nin sunduğu parametre bağlama yöntemlerini kullanın.

Veritabanı Yönetim Yöntemlerinin Karşılaştırılması

Yöntem Avantaj Dezavantaj
SQLAlchemy ORM Nesne yönelimli, veritabanından bağımsız Öğrenme eğrisi biraz yüksek
SQLAlchemy Core Daha hızlı, SQL'e yakın Daha fazla kod yazımı gerektirir
Ham SQL (sqlite3) Basit, hızlı kurulum Güvenlik riskleri ve bakım zorluğu

Veri Güncelleme ve Silme

Mevcut bir kaydı güncellemek veya silmek için önce nesneyi sorgulamalı, ardından üzerinde değişiklik yapmalısınız. SQLAlchemy, nesne üzerindeki değişiklikleri takip eder (dirty tracking) ve commit çağrıldığında bu değişiklikleri veritabanına yansıtır.

with Session(engine) as session:
    # Güncelleme
    kullanici = session.scalar(select(Kullanici).where(Kullanici.isim == "Ahmet Yılmaz"))
    if kullanici:
        kullanici.email = "yeni_email@example.com"
        session.commit()
    
    # Silme
    # session.delete(kullanici)
    # session.commit()

Sıkça Sorulan Sorular

SQLAlchemy ile veritabanı şemasını nasıl güncellerim?

SQLAlchemy'nin create_all metodu sadece tablolar yoksa oluşturur. Şema değişiklikleri için Alembic adlı kütüphaneyi kullanmanız önerilir. Alembic, veritabanı göçlerini (migrations) yönetmek için standart araçtır.

Neden ham SQL yerine ORM kullanmalıyım?

ORM, veritabanı motorundan bağımsız kod yazmanızı sağlar. Yarın SQLite'tan PostgreSQL'e geçmek isterseniz, sadece bağlantı dizisini değiştirmeniz yeterli olur; kodunuzun geri kalanı değişmez.

Session nesnesi neden her seferinde açılmalı?

Session, veritabanı ile olan bağlantı havuzunu yönetir. Uzun süre açık kalan oturumlar, veritabanı bağlantı limitlerine takılmanıza veya bayat (stale) veri okumanıza neden olabilir.

SQLAlchemy performansı ham SQL'den düşük müdür?

Çok küçük farklar olsa da, modern donanımlarda bu fark ihmal edilebilir düzeydedir. ORM'in sağladığı geliştirme hızı ve hata azaltma avantajları, performans maliyetinden çok daha değerlidir.

İlişkisel veritabanlarında tablolar arası ilişki nasıl kurulur?

ForeignKey ve relationship sınıfları kullanılarak bir tablo diğerine bağlanabilir. Bu sayede kullanici.adresler gibi bir ifadeyle ilişkili veriye kolayca ulaşabilirsiniz.

Yasal Uyarı: Bu rehber eğitim amaçlıdır. Uygulamanızda kullanacağınız veritabanı şifrelerini ve hassas bilgileri asla kod içerisinde açık metin olarak saklamayın. Çevresel değişkenler (environment variables) veya güvenli kasa (vault) sistemlerini kullanın.

SQLAlchemy Projelerinde Hata Ayıklama ve Loglama Teknikleri

Karmaşık veritabanı işlemlerinde, SQLAlchemy'nin arka planda hangi SQL sorgularını çalıştırdığını görmek hata ayıklama sürecini hızlandırır. SQLAlchemy, yerleşik bir loglama mekanizmasına sahiptir. Bu mekanizmayı aktif ederek, veritabanı trafiğini terminalinizde canlı olarak izleyebilirsiniz.

Aşağıdaki yapılandırma, tüm SQL sorgularını ve parametrelerini konsola yazdırır:

import logging
from sqlalchemy import create_engine

# SQLAlchemy loglarını aktif et
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

engine = create_engine('sqlite:///veritabani.db', echo=True)

İpucu: Üretim (production) ortamında echo=True parametresini mutlaka kapatın, aksi takdirde hassas verileriniz log dosyalarına sızabilir.

Veritabanı İşlemlerinde Hata Yönetimi

Veritabanı işlemleri sırasında bağlantı kopmaları veya kısıt ihlalleri (constraint violations) gibi beklenmedik hatalar oluşabilir. Bu tür durumları yönetmek için try-except bloklarını ve SQLAlchemy'nin kendi hata sınıflarını kullanmalısınız.

from sqlalchemy.exc import SQLAlchemyError

try:
    session.add(yeni_kullanici)
    session.commit()
except SQLAlchemyError as e:
    session.rollback()
    print(f"Veritabanı hatası oluştu: {e}")
finally:
    session.close()

SQLAlchemy ile Performans Optimizasyonu

ORM kullanımı kolaylık sağlasa da, yanlış sorgu yapıları "N+1 problemi" gibi performans darboğazlarına yol açabilir. Veritabanı performansını artırmak için aşağıdaki stratejileri uygulayabilirsiniz:

  • Eager Loading (Önceden Yükleme): İlişkili verileri tek bir sorguda çekmek için joinedload veya subqueryload kullanın.
  • Sadece İhtiyaç Duyulan Sütunları Çekme: session.query(User.id, User.name) şeklinde sadece gerekli alanları seçerek bellek kullanımını azaltın.
  • Batch Insert: Çok sayıda veriyi tek seferde eklemek için session.bulk_save_objects() metodunu tercih edin.

Eager Loading Kullanımı

İlişkili tabloları sorgularken, her bir satır için ayrı bir sorgu gitmesini engellemek adına joinedload kullanımı kritiktir:

from sqlalchemy.orm import joinedload

# Kullanıcıları ve bağlı oldukları adresleri tek sorguda getirir
kullanicilar = session.query(User).options(joinedload(User.addresses)).all()

for k in kullanicilar:
    print(k.name, [a.email for a in k.addresses])

Bu yöntem, özellikle büyük veri setleri ile çalışırken veritabanı üzerindeki yükü ciddi oranda düşürür ve uygulamanızın yanıt süresini optimize eder.

Sonuç

Python ile SQLAlchemy kullanarak veritabanı yönetimi, profesyonel bir yazılım geliştirme sürecinin temel taşıdır. Bu rehberde bağlantı kurmayı, model oluşturmayı, veri işlemeyi ve sorgulamayı adım adım öğrendiniz. SQLAlchemy'nin sunduğu esneklik ve güvenlik, projelerinizin uzun vadeli başarısı için kritik öneme sahiptir. Bir sonraki adım olarak, veritabanı göçlerini yönetmek için Alembic kütüphanesini araştırmanızı ve karmaşık ilişkili veriler (One-to-Many, Many-to-Many) üzerine pratik yapmanızı öneririm.

Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Hobi projeleri ve kendin yap (DIY) içerikleri üzerine uzmanlaşmış bir içerik editörüyüm. Adım adım rehberlerle okuyucuların teknik becerilerini geliştirmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz