DEV Community

Cover image for Python ORM: Peewee
Abdullah Emiroğlu
Abdullah Emiroğlu

Posted on • Updated on

Python ORM: Peewee

Not: SQLAlchemy tabanlı SQLModel'ı incelemek isteyebilirsiniz.

Resmi belge için: Peewee Docs

Aşağıdaki kavramları/teknolojileri en azından temel seviyede bildiğinizi varsayıyorum:


Bu yazıda, dilim döndüğünce, bilgim ölçüsünde Python için kolay ama etkili bir ORM olan Peewee'ye hızlı bir giriş yapıyoruz.

Yazı boyunca, kitaplık veritabanı (Github) oluşturarak Peewee'nin temel özelliklerini bu örnek üzerinden görmüş olacağız, umarım faydalı olur.

İçerik:

NEDEN PEEWEE?

Kolay; öğrenme eğrisi düşük.
Yeterli konsept; sahip olduğu konseptler, muhtemelen işinizi görecek kadar yeterli.
Başlangıç için ideal; ORM mantığını kavramak ve kısa zaman içerisinde elle tutulur çalışmalar ortaya çıkarmak mümkün. Bu, motivasyonu arttırabilir.
Bilinir; Python camiasında bilinen bir ORM, yani bir şekilde destek bulursunuz. (Fakat popüler değil)
Türkçe kaynak katkısı yapmayı amaçladım.

SENARYO

Modellerimiz (Veritabanı Tablolarımız):

  • Kitap
  • Okuyucu
  • OkunanKitap
  • Yazar
  • KitapDetay

Ulaşmak istediğimiz bazı veriler:

  • Kitap listesi.
  • Kitabı okuyanlar kimler?
  • Okuyucu listesi ve her birinin kaç kitap okuduğu.
  • Okuyucu hangi kitapları okudu?
  • Kitap bilgileri.

HAZIRLIK

Hatırlatma!
Windows kullanıcıları python3 yerine, py kullanmalıdır.

Komut satırını başlatıyoruz...

kitaplik isminde bir dizin/klasör oluşturup, geçiş yapalım:

mkdir kitaplik
cd kitaplik
Enter fullscreen mode Exit fullscreen mode

KURULUM

Python Paket Yöneticisi (PIP) ile kurmak için:

pip3 install peewee
Enter fullscreen mode Exit fullscreen mode

Sanal Ortama Kurulum | Bu adımı geç

Önemli! Bazı GNU/Linux dağıtımlarında python3-venv tarzı bir paket kurmak gerekebiliyor.

1) Sanal ortamı oluşturalım:

python3 -m venv env
Enter fullscreen mode Exit fullscreen mode

Hatırlatma!
"env" yerine istediğiniz bir ismi de yazabilirsiniz (ör: sanal_peewe.) Bir sonraki adımda env yerine belirlediğiniz ismi yazmanız gerekir.

2) Sanal ortamı aktif hale getirelim:

source env/bin/activate
Enter fullscreen mode Exit fullscreen mode

Hatırlatma! Eğer Windows kullanıyorsanız şu komutu vermelisiniz:

env\Scripts\activate.bat

3) Paket yöneticimizi (PIP) güncelleyelim:

python3 -m pip install --upgrade pip
Enter fullscreen mode Exit fullscreen mode

4) Ve kurulum komutumuzu verelim:

python3 -m pip install peewee
Enter fullscreen mode Exit fullscreen mode

Böylece kitaplik klasörümüze sanal ortamımızı, sanal ortamımıza da Peewee'yi kurmuş olduk.

5) Kontrol edelim:
GNU/Linux üzerinde komut satırı


VERİTABANI TANIMLAMA

Kodlamaya başlıyoruz...

0) VS Code kullanıyorsak editörümüzü, "kitaplik" dizinimiz üzerinde başlatalım:

code .
Enter fullscreen mode Exit fullscreen mode

1) models.py isminde bir dosya oluşturalım ve açalım.

2) peewee modülünü pw olarak kullanmak üzere models.py dosyamıza tanımlayalım/aktaralım:

import peewee as pw
Enter fullscreen mode Exit fullscreen mode

3) Veritabanımızı tanımlayalım:

import peewee as pw

db = pw.SqliteDatabase("kitaplik.db")
Enter fullscreen mode Exit fullscreen mode

Ek bilgi
Veritabanını açmak için db.connect(), kapatmak için db.close() kullanabiliriz.


TABLOLARI MODELLEME

Peewee'de ilişkisel veritabanına karşılık gelen kavramlar şu şekildedir:

Kavram Karşılığı
Model Sınıfı (Model Class) Veritabanı Tablosu
Kolon/Alan Örneği (Field Instance) Veritabanı Tablo Kolonu
Model Örneği (Model Instance) Veritabanı Tablo Satırı

Şimdi, yukarıdaki bilgileri senaryomuz üzerinde görelim.

İlişkisel veritabanında "kitap", "okuyucu" ve "okunan_kitap" isimli tablolar oluşturmanın Peewee'deki karşılığı şu şekilde olur:

1) Tablomuzu peewee.Model sınıfından türeterek, sınıf olarak tanımlarız:

class Kitap(pw.Model):
Enter fullscreen mode Exit fullscreen mode

Ek bilgi
Şu güncellemeyi incelemek isteyebilirsiniz: 3.15.4

2) Kolonlarımızı/Alanlarımızı peewee.NameField sınıflarını kullanarak tanımlarız:

class Kitap(pw.Model):
    isim = pw.CharField(max_length=250, null=False, unique=True)
Enter fullscreen mode Exit fullscreen mode

Yukarıda isim kolonu/alanı;

  • En fazla 250 karakter olabilir.
  • Boş olamaz.
  • Tekrar edemez (benzersiz olmalıdır.)

3) Modelimizin hangi veritabanını kullanacağını ve diğer ayarları, alt bir Meta sınıfı yazarak tanımlarız:

class Kitap(pw.Model):
    isim = pw.CharField(max_length=250, null=False, unique=True)

    Class Meta:
        database = db
        legacy_table_names = False
Enter fullscreen mode Exit fullscreen mode

Yukarıda Kitap modelimiz;

  • id isminde ve her kayıtta değeri otomatik olarak 1 er artacak bir alan/kolon oluşacak:

id = pw.IntegerField(primary_key=True)

  • Veritabanı olarak -daha önce tanımladığımız- db değişkenini kullanacak.
  • Veritabanında tablo ismi, kucuk_isim biçiminde oluşacak.

4) Şimdi Okuyucu modelimizi tanımlayabiliriz.

Ama öncesinde models.py dosyamızın baş tarafına Modelimiz isminde şöyle bir sınıf tanımlayalım:

import peewee as pw

db = pw.SqlDatabase("kitaplik.db")

class Modelimiz(pw.Model):
    class Meta:
        database = db
        legacy_table_names = False
Enter fullscreen mode Exit fullscreen mode

Kaldığımız yerden devam edelim ve Okuyucu modelimizi, Modelimiz sınıfından türeterek tanımlayalım:

class Okuyucu(Modelimiz):
    isim = pw.CharField(max_length=250, null=False, unique=True)
Enter fullscreen mode Exit fullscreen mode

Okuyucu modelimiz ile, Kitap modelimiz arasındaki ilişkiyi de tanımlayalım:

class Okuyucu(Modelimiz):
    isim = pw.CharField(max_length=250, null=False, unique=True)
    kitaplar = pw.ManyToManyField(Kitap, backref="okuyucular")

OkunanKitap = Okuyucu.kitaplar.get_through_model()
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • Meta sınıfı yazmamıza gerek kalmadı. Çünkü Modelimiz sınıfından türeterek tanımladık.
  • peewee.ManyToManyField kullanarak Okuyucu ve Kitap arasında çoka-çok ilişki tanımladık. backref parametresini kullanarak; kitap üzerinden okuyuculara ulaşabilmeyi sağlayan bir anahtar ifade tanımlamış olduk.
  • OkunanKitap, iki model arasındaki ilişki için gereklidir.

Çoka-çok İlişki?

Çoka-çok ilişki bize şunu söyler; okuyucu, birden fazla kitabı okumuş olabilir.

Aynı şekilde kitabı, birden fazla okuyucu okumuş olabilir.

Ek bilgi
Eğer elimizde okuyucu varsa, okuduğu kitaplara şu şekilde ulaşırız:

okuyucu.kitaplar

Eğer elimizde kitap varsa, kitabı okuyanlara şu şekilde ulaşırız:

kitap.okuyucular

5) Son olarak modellerimizi veritabanına aktarabilmek için, models.py dosyamıza db.create_tables([]) eklememiz gerekiyor:

db.create_tables([
    Kitap,
    Okuyucu,
    OkunanKitap
])
Enter fullscreen mode Exit fullscreen mode

models.py dosyamızın son hali:

models.py modülü

Şimdi komut satırımıza dönelim ve modellerimizi veritabanına aktaralım:

python3 models.py
Enter fullscreen mode Exit fullscreen mode

CRUD İŞLEMLERİ

CRUD?

  • Create - Oluştur/Ekle
  • Read - Oku/Seç/Listele
  • Update - Güncelle
  • Delete - Sil

Hazırlık

crud.py isminde yeni bir dosya oluşturalım ve içerisine şu şekilde bir yapı tanımlayalım:

crud.py modülü (şablon)

Yukarıda;
Sadece istediğimiz kod bloğunu çalıştırabilmek için, dosyamızı fonksiyon parçalarına böldük.

Kayıt Ekleme (Create)

İlk kısım olan, create() fonksiyonumuzu kodluruyoruz...

1) Kitap ve okuyucu kaydı tanımlayalım:

k1 = Kitap(isim="Martin Eden")
k1.save()
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • Kitap modelimizden yeni bir kitap örneği oluşturduk.
  • save() metodu ile kaydımızı gerçekleştirdik.

2) Bu sefer create metodu ile okuyucu kaydı tanımlayalım:

o1 = Okuyucu.create(isim="Abdullah")
Enter fullscreen mode Exit fullscreen mode

3) Şimdi de o1(Abdullah) okuyucusuna, k1(Martin Eden) kitabını tanımlayalım:

o1.kitaplar.add(k1)
Enter fullscreen mode Exit fullscreen mode

Hatırlatma!
Okuyucu modelimize kitaplar isminde kolon tanımlamıştık.

4) İsterseniz farklı bir yöntem kullanarak yeni bir kitap kaydı tanımlayalım:

kitap_id = Kitap.insert(isim="Cinayet Alfabesi").execute()
Enter fullscreen mode Exit fullscreen mode

Ek bilgi
execute() metodu, kaydı gerçekleştirir ve int tipinde benzersiz bir kayıt id değeri döndürür.

5) Şimdi Model.get() kullanarak az önceki kitap kaydımıza ulaşalım.
Ardından o1(Abdullah) okuyucusuna k2(Cinayet Alfabesi) kitabımızı tanımlayalım:

k2 = Kitap.get(Kitap.id == kitap_id)
k2.okuyucular.add(o1)
Enter fullscreen mode Exit fullscreen mode

Hatırlatma!
Okuyucu modelimizde yer alan kitaplar kolonunun parametresi, backref="okuyucular" şeklindeydi.

crud.py modülünün, create() fonksiyonu

Kayıt Listeleme (Read)

read() fonksiyonumuzu kodluyoruz...

1) Model.select() ve for döngüsü kullanarak kitaplarımızı listeleyebiliriz:

kitaplar = Kitap.select()
for kitap in kitaplar:
    print(kitap.id, kitap.isim)
Enter fullscreen mode Exit fullscreen mode

"Kitabı oyuyan her bir kişiyi" listelemek için alt for döngüsü tanımlayalım:

    for okuyucu in kitap.okuyucular:
        print(okuyucu.isim)
Enter fullscreen mode Exit fullscreen mode

Ek bilgi

  • Model.select().count() veya len(Model.select()) kullanarak, sorgu sonucunun kaç adet kayıt barındırdığını öğrenebiliriz.
  • Model.select().sql() kullanarak da sorgunun SQL karşılığına ulaşabiliriz.

2) Okuyucuları ve okudukları kitap sayısını listeleyelim:

for okuyucu in Okuyucu.select():
    print(okuyucu.isim, okuyucu.kitaplar.count())
Enter fullscreen mode Exit fullscreen mode

crud.py modülünün, read() fonksiyonu

Buraya kadar yaptığımız değişiklikleri görmek için;
crud.py dosyamızın en altına, fonksiyon çağrımızı ekleyelim:

create()
read()
Enter fullscreen mode Exit fullscreen mode

Şimdi komut satırımıza dönelim ve sonucu görelim:

python3 crud.py
Enter fullscreen mode Exit fullscreen mode

GNU/Linux üzerinde komut satırı

Kayıt Güncelleme (Update)

update() fonksiyonumuzu kodluyoruz...

1) İlk olarak, kitabımıza ulaşmak için gerekli tanımlamayı yapalım:

martin_eden = Kitap.get(Kitap.isim == "Martin Eden")
Enter fullscreen mode Exit fullscreen mode

2) Değişikliğimizi tanımlayalım:

martin_eden.isim = "Martin Ede"
Enter fullscreen mode Exit fullscreen mode

3) Kaydı gerçekleştirmek ve değişikliği ekrana yazdırabilmek için ekleyelim:

martin_eden.save()
print(martin_eden.isim)
Enter fullscreen mode Exit fullscreen mode

4) Şimdi de farklı bir yöntem kullanarak güncelleme tanımlaması yapalım:

Kitap.update(isim="Martin Eden").where(Kitap.id == martin_ed
den.id).execute()
Enter fullscreen mode Exit fullscreen mode

execute() metodu, işlemi gerçekleştirir ve güncellenen satır sayısını int tipinde döndürür.

5) Hemen ardından değişikliği görebilmek için ekleyelim:

martin_eden = Kitap.get(Kitap.id == martin_eden.id)
print(martin_eden.isim)
Enter fullscreen mode Exit fullscreen mode

Image description

5) Son olarak crud.py dosyamızın en sonuna fonksiyon çağrımızı da ekleyelim:

#create()
#read()
update()
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • create() ve read() çağrılarımızı "yorum satırına" döndürdük ki çalışmasınlar.

Şimdi komut satırımıza dönelim ve sonucu görelim:

python3 crud.py
Enter fullscreen mode Exit fullscreen mode

Image description

Çoklu Kayıt

multi_create() fonksiyonumuzu kodluyoruz...

1) Öncelikle şu şekilde tuple barındıran bir liste tanımlıyoruz:

veriler = [("Musullu Süleyman",),
           ("İsimsiz",),
           ("İnsanları Okumak",),
           ("Bilim Ne değildir?",)]
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
tuple satır kolonlarını temsil ediyor, örneğimizde tek kolon olduğu için, ("Veri1",) şeklinde yazdık.

2) Kitapları kaydetmek için ekleyelim:

Kitap.insert_many(veriler, fields=[Kitap.isim]).execute()
Enter fullscreen mode Exit fullscreen mode

3) Okuyucuları farklı bir yöntemle kaydetmek için, şu şekilde tanımlama yapalım:

veriler = [{"isim": "İsimsiz"},
           {"isim": "Sefa"}]
Okuyucu.insert_many(veriler).execute()
Enter fullscreen mode Exit fullscreen mode

Bu seferki örneğimizde veriler isimli listemiz, dict tipinde kolonlar barındırıyor. Ayrıca insert_many() metodu, fields=[] parametresi almıyor.

Kaydettiğimiz kitaplara, kaydettiğimiz okuyucuları tanımla işlemiyle devam ediyoruz...

4) Okuyuculara ulaşalım:

isimsiz = Okuyucu.get(Okuyucu.isim.contains("siz"))
abdullah = Okuyucu.get(Okuyucu.isim.startswith("A"))
sefa = Okuyucu.get(Okuyucu.isim.endswith("fa"))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • "siz" ifadesi geçen kayıt getirilecek.
  • "A" ile başlayan kayıt getirilecek.
  • "fa" ile biten kayıt getirilecek.

Ek bilgi

  • Bu metotlar, where() içeriside de kullanılabilir.
  • Ek olarak; between(), in_(), not_in(), ... gibi birçok metot mevcut.

5) Aranacak kitap ve tanımlanacak okuyucu listeleri oluşturalım:

aranacaklar = ["isi", "mus", "oku", "bil"]
okuyucular = [isimsiz, [abdullah, sefa], abdullah, [abdullah, sefa]]
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
2 liste de aynı sayıda eleman içermekte, birden fazla okuyucu alt liste içerisinde tanımlanmakta.

6) for döngüsü yardımıyla tanımlamaları gerçekleştirelim:

index = 0
for aranan in aranacaklar:
    kitap = Kitap.get(Kitap.isim.contains(aranan))
    okuyucu = okuyucular[index]

    if type(okuyucu) == list:
        for _okuyucu in okuyucu:
            kitap.okuyucular.add(_okuyucu)
    else:
        kitap.okuyucular.add(okuyucu)

    index += 1
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • index değişkeni, listelerin index değerini barındırıyor.
  • Döngü boyunca kitap aranıyor ve bulunan kitap, kitap değişkenine aktarılıyor. Kitabı okuyan okuyucu ise, okuyucular listesinden index yardımıyla okuyucu değişkenine aktarılıyor.
  • Eğer kitabı okuyan okuyucu birden fazla ise (yani liste tipindeyse); alt for döngüsü çalışıyor, her bir okuyucu, kitaba tanımlanıyor.
  • Eğer kitabı okuyan okuyucu tek ise; kitaba okuyucu tanımlanıyor.
  • Döngü boyunca index değeri 1 arttırılıyor.

Image description

Kayıt Silme (Delete)

Delete() fonksiyonumuzu kodluyoruz...

1) Silinecek kayıtarımızı tanımlayalım:

kitap = Kitap.get(Kitap.isim == "İsimsiz")
okuyucu = Okuyucu.get(Okuyucu.isim == "İsimsiz")
Enter fullscreen mode Exit fullscreen mode

2) Okuyucuya tanımlanan kitabı silebilmek için ekleyelim:

okuyucu.kitaplar.remove(kitap)
Enter fullscreen mode Exit fullscreen mode

Ya da tam tersi:

kitap.okuyucular.remove(okuyucu)
Enter fullscreen mode Exit fullscreen mode

Ek bigi
clear() metodu ilişkili bütün kayıtları siler.

3) Şimdi kitabı silebilmek için tanımlalım:

kitap.delete_instance()
Enter fullscreen mode Exit fullscreen mode

4) Son olarak, okuyucuyu farklı şekilde silebilmek için ekleyelim:

Okuyucu.delete().where(Okuyucu.id == okuyucu.id).execute()
Enter fullscreen mode Exit fullscreen mode

execute() metodu, işlemi gerçekleştirir ve silinen satır sayısını int tipinde döndürür.

Image description


JOIN İŞLEMLERİ

JOIN?

Birden fazla modelden tek seferde veri çekilmesi gerektiğinde devreye join işlemi girer. Modellerimize tanımladığımız peewee.ForeignKeyField, peewee.ManyToManyField gibi ilişki kolonları sayesinde modelleri birleştirebiliyoruz.

Hazırlık

1) join.py isminde yeni bir dosya oluşturalım ve içerisine şu şekilde bir yapı tanımlayalım:
Image description

Yukarıda;

  • Tarih işlemleri için datetime modülünü içe aktardık.
  • models.py dosyamızda yer alan ve ihtiyacımız olacak modelleri içe aktardık.
  • İlk defa peewee.IntegerField, peewee.DateField, peewee.FloatField kullanan modeller tanımladık.
  • peewee.ForeignKeyField kullanarak modeller arası bire-bir(Kitap-KitapDetay) ve bire-çok(Yazar-Kitap) ilişkiler tanımladık.

Bire-bir İlişki?

Bire-bir ilişki bize şunu söyler; bir kitabı, bir yazar yazabilir veya bir kitabın, bir tane fiyatı olabilir.

Yani KitapDetay modelinde yer alan kitap kolonu, bir kez kullanılabilir, aynı kitap tekrar edemez.

class KitapDetay(Modelimiz):
    kitap = pw.ForeignKeyField(Kitap, backref="kitaplar", primary_key=True)
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
primary_key=True parametresi sayesinde; benzersiz id kolonu oluşturulmaz yerine kitap_id ayarlanır. kitap_id, Kitap modelinin id kolonununa karşılık gelir. (KitapDetay.kitap_id == Kitap.id)

Bire-çok İlişki?

Bire-çok ilişki bize şunu söyler; yazar, birden çok kitap yazmış olabilir.

Yani KitapDetay modelinde yer alan yazar kolonu, birden fazla kez tekrar edebilir.

class KitapDetay(Modelimiz):
    kitap = pw.ForeignKeyField(Kitap, backref="kitaplar", primary_key=True)
    yazar = pw.ForeignKeyField(Yazar, backref="yazarlar")
Enter fullscreen mode Exit fullscreen mode

Somut bir örnek olarak;
"Martin Eden" kitabı bir kere yer alabilirken, "Jack London" yazarı birden fazla kez yer alabilir. (Jack London'ın başka bir kitabını eklemek isteyebiliriz ;)

2) Daha önceki bilgilerimizi kullanarak create() fonksiyonumuzu kodlayalım:

Image description

Yukarıda;

  • Yeni yazarlar kaydedilecek.
  • kitaplar listesi üzerinde for döngüsü çalışacak. Döngü boyunca; "kitap" ve "okuyucu" bilgileri Model.get() ve -aynı görevi gören- Model.select().where().get() ile alınacak.
  • index değişkeni sayesinde karşılık gelen "tarih" ve "fiyat" bilgileri de alınacak, ardından bütün bu bilgiler dict tipinde veriler listesine eklenecek.
  • Son olarak döngü sonucunda oluşan veriler listesi, KitapDetay modelimize kaydedilecek.

Kitap Detaylarını Listeleme

Bunun için KitapDetay, Kitap ve Yazar modellerini birleştirmemiz gerekecek.

1) İlk tanımlamamızı gerçekleştirelim:

kitaplar = (KitapDetay
            .select(Kitap.isim,
                    Yazar.isim.alias("yazar"),
                    KitapDetay.tarih,
                    KitapDetay.fiyat))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • Sorgumuzu () içerine alarak, çok satırlı bir şekilde yazım gerçekleştirebildik.
  • alias() metodu, kolonlara arzuladığımız bir isim verebilmeyi sağlıyor. (Örneğimizde hem kitap ismi, hem de yazar ismi aynı anda yer aldığı için, karışmasını engelledik.)

2) join() metodunu kullanarak Kitap modelimizi, switch() ve join() metotlarıyla da Yazar modelimizi birleştirmek için parantezin içerisine ekleyelim:

...
.join(Kitap)
.switch(KitapDetay)
.join(Yazar))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • switch() metodu sayesinde Yazar modeli, Kitap modeliyle değil KitapDetay modeliyle birleşecek. Tersi durumda bu iki tablo arasında bir ilişki olmadığı için hata alacaktık.

Ek bilgi

  • Yalnızca where() kullanarak veya şu şekilde zincirleme ifadeler kullanarak filtrelemeler yapmak mümkün:
...
.join(Yazar)
.where(Yazar.isim == "Martin Eden")
.where(KitapDetay.fiyat < 60)
.orwhere(KitapDetay.tarih.year >= 1995))

Hatırlatma; bu ifadelerin SQL karşılığını görmek için; kitaplar.sql() kullanabiliriz.

3) Listeyi tarihe göre sıralamak için parantezin içine ekleyelim:

...
.order_by(KitapDetay.tarih.desc()))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
desc() son tarih başta olsun demek oluyor. Eğer sadece kolon ismi belirtirsek, asc() kullanılmış gibi varsayılır ve bu durumda, ilk tarih başta olsun demiş oluruz.

Ek bilgi
Sorgumuzun sonuna; limit(3)(Kaç adet kayıt listeleneceği), distinct()(Yalnızca tekrar etmeyen kayıtların listeleneceği) gibi metotlar ekleyebiliriz.

4) Son olarak listeleme işlemini gerçekleştirmek için tanımlayalım:

for kitap in kitaplar.dicts():
        print(kitap)
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • dicts(), satırları "sözlük veri tipinde(dict)" almamızı sağlar.

Ek bilgi
tuples() veya namedtuples() kullanmak da mümkün.

Image description

Okuyucuları Listeleme

read() fonksiyonumuzu kaldığımız yerden kodlamaya devam ediyoruz...

1) Öncelikle bu kez select()'de kullanacağımız kolonları ayrı tanımlayalım:

miktar = pw.fn.COUNT(OkunanKitap.kitap_id).alias("okunan_miktar")
birlesik = Okuyucu.isim.concat("+").concat(Kitap.isim).alias("birlesik")
Enter fullscreen mode Exit fullscreen mode

Yukarıda;

  • miktar değişkenine atadığımız kolon; peewee.fn.COUNT() 'u kullanarak OkunanKitap.kitap_id'nin kaç adet olduğunu öğrenmemizi sağlayacak.
  • birlesik değişkenine atadığımız kolon; concat() metodunu kullanarak Okuyucu.isim ve Kitap.isim kolonlarını aralarına "+" işareti koyarak birleştirmemizi (tek kolon haline getirmemizi) sağlayacak.

Ek bilgi
alias() metodunu modeller için de kullanabiliriz:

model = Model.alias("model_name")

2) Bu adımda okuyucular değişkenimizin sorgusunu tanımlamaya başlayalım:

okuyucular = (Okuyucu
              .select(Okuyucu.isim, miktar, birlesik)
Enter fullscreen mode Exit fullscreen mode

3) OkunanKitap ve Kitap modellerimizi birleştirelim:

...
.join(OkunanKitap, pw.JOIN.LEFT_OUTER,
      on=(Okuyucu.id == OkunanKitap.okuyucu_id))
.join(Kitap, pw.JOIN.LEFT_OUTER,
      on=(Kitap.id == OkunanKitap.kitap_id))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
join() metodunu, birleşim türü (LELFT_OUTER, RIGHT_OUTER, vb.) ve birleşim tercihi (on=()) ile beraber kullandık.

4) Her bir okuyucunun okuduğu kitap sayısını listelettireceğimiz için, okuyucu grubu tanımlayalım:

...
.group_by(Okuyucu.id)
.order_by(miktar, Okuyucu.isim))
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
order_by() metoduna, birden fazla sıralanacak kolon tanımlanıyor.

5) Son olarak okuyucular listemizi görüntüleyelim:

for okuyucu in okuyucular.objects():
   print(okuyucu.isim,
         okuyucu.okunan_miktar,
         okuyucu.birlesik)
Enter fullscreen mode Exit fullscreen mode

Yukarıda;
objects() her bir satırı nesne olarak kullanmamızı sağlıyor.

Image description

6) Şimdi komut satırına dönelim ve sonucu görelim:

python join.py
Enter fullscreen mode Exit fullscreen mode

GNU/Linux üzerinde komut satırı

Böylece bu yazının sonuna geldik. Bir başka yazıda görüşmek üzere...

Top comments (0)