Django ORM ve QuerySets (SorguSetleri)

Bu bölümde Django'nun veritabanına nasıl bağlandığını ve veriyi nasıl sakladığını öğreneceğiz. Hadi başlayalım!

QuerySet (SorguSeti) Nedir?

QuerySet (SorguSeti), esas olarak, verilen bir modele ait nesnelerin listesidir. QuerySet veritabanından veri okumamıza, veriyi filtrelememize ve sıralamamıza imkan sağlar.

En kolayı örnek ile öğrenmektir. Hadi deneyelim, olur mu?

Django shell (kabuk)

Bilgisayarımızdaki konsolu açalım (PythonAnywhere'dekini değil) ve şu komutu yazalım:

komut-satırı

(myvenv) ~/djangogirls$ python manage.py shell

Etkisi aşağıdaki gibi olmalı:

komut-satırı

(InteractiveConsole)
>>>

Şu an Django'nun etkileşimli konsolundayız. Python istemine benziyor, ama biraz Django büyüsü eklenmiş :) Kuşkusuz burada da Python komutlarının tümünü kullanabiliriz.

Tüm nesneler

Önce tüm post'larımızı görüntülemeyi deneyelim. Bunu aşağıdaki komut ile yapabiliriz:

komut-satırı

>>> Post.objects.all()
Traceback (most recent call last):
      File "<console>", line 1, in <module>
NameError: name 'Post' is not defined

Ahh! Bir hata meydana geldi. Bize Post'un tanımlı olmadığını söylüyor. Bu doğru, öncesinde post'u dahil etmeyi (import) unuttuk!

komut-satırı

>>> from blog.models import Post

blog.models'dan Post modelini dahil ettik (import). Tekrar bütün post'ları görüntülemeyi deneyelim:

komut-satırı

>>> Post.objects.all()
<QuerySet [<Post: Gönderi başlığım>, <Post: Diğer bir gönderi başlığı>]>

Bu daha önce oluşturduğumuz post'ların listesi! Bu post'ları Django admin arayüzü ile oluşturduk. Fakat şimdi Python kullanarak yeni post'lar oluşturmak istiyoruz, peki bunu nasıl yaparız?

Nesne oluşturma

Veritabanına yeni bir gönderi eklemek için:

komut-satırı

>>> Post.objects.create(author=ben, title='Harika bir gönderi', text='Ne desem bilemedim')

Ancak bir eksiğimiz var: ben. Gönderinin author (yazar) özelliğine User (kullanıcı) modelinden türetilen bir nesneyi parametre olarak vermemiz gerekiyor. Nasıl verebiliriz?

Öncelikle User (kullanıcı) modelini dahil edelim:

komut-satırı

>>> from django.contrib.auth.models import User

Veritabanımızda hangi kullanıcılar var? Şu şekilde görebiliriz:

komut-satırı

>>> User.objects.all()
<QuerySet [<User: zeynep>]>

Bu daha önce yarattığımız süper kullanıcı (superuser)! Şimdi bu kullanıcının örneğini (instance) alalım (bu satırı kendi kullanıcı adınızı kullanmak için değiştirin):

komut-satırı

ben = User.objects.get(username='zeynep')

Görebildiğiniz gibi, şimdi kullanıcı adı 'zeynep' olan bir User aldık. Temiz!

Gönderimizi artık kaydedebiliriz:

komut-satırı

>>> Post.objects.create(author=ben, title='Harika bir gönderi', text='Ne desem bilemedim')
<Post: Harika bir gönderi>

Yaşasın! Çalışıp çalışmadığını kontrol etmek ister misin?

komut-satırı

>>> Post.objects.all()
<QuerySet [<Post: Gönderi başlığım>, <Post: Diğer bir gönderi başlığı>,<Post: Harika bir gönderi>]>

İşte bu kadar, listede bir gönderi daha!

Daha fazla post ekle

Şimdi daha fazla post ekleyerek biraz eğlenebilir ve nasıl çalıştığını görebiliriz. İki veya üç tane daha ekleyelim ve sıradaki bölüme geçelim.

Nesneleri filtrelemek

QuerySet'lerin büyük bir bölümü nesneleri filtreleme yeteneğidir. Diyelim ki, Zeynep tarafından yazılmış tüm post'ları (gönderileri) bulmak istiyoruz. Post.objects.all() içindeki all yerine filter kullanacağız. Parantez içine istediğimiz blog gönderilerinin sağlaması gereken şartları belirteceğiz. Örneğimizde, author ben'e eşitti. Django'da bu filtreyi şöyle yazıyoruz: author=ben. Şu an kod parçacığımız şöyle görünüyor:

komut-satırı

>>> Post.objects.filter(author=ben)
[<Post: Gönderi 1>, <Post: Gönderi 2>, <Post: Harika bir gönderi>, <Post: Nefis bir gönderi>]

Ya da belki title (başlık) alanında içinde 'Nefis' kelimesini içeren tüm gönderileri görmek istiyoruz?

komut-satırı

>>> Post.objects.filter(title__contains='Nefis')
[<Post: Nefis bir gönderi>]

Not title ve contains arasında iki tane alt çizgi (_) var. Django'nun ORM'i bu söz dizimini, özelliği ("title") ve operasyon veya filtreyi ("contains") ayırmak için kullanır. Eğer sadece tek bir alt çizgi kullanırsanız, "FieldError: Cannot resolve keyword title_contains" şeklinde bir hata alacaksınız.

Ayrıca yayınlanmış tüm post'ların bir listesini alabiliriz. Bunu published_date (yayinlanma_tarihi) alanı geçmiş bir tarih olan tüm gönderileri filtreleyerek yapıyoruz:

komut-satırı

>>> from django.utils import timezone
>>> Post.objects.filter(published_date__lte=timezone.now())
<QuerySet []>

Maalesef python konsolundan eklediğimiz post (gönderi) henüz yayınlanmadı. Fakat bunu değiştirebiliriz! Önce yayınlamak istediğimiz bir gönderi nesnesi bulalım:

komut-satırı

>>> post = Post.objects.get(title="Harika bir gönderi")

Ardından publish (yayinla) methodu ile gönderiyi yayınlayalım:

komut-satırı

>>> post.publish()

Şimdi yayınlanmış gönderileri tekrar almaya çalışalım (3 kez yukarı ok tuşuna ve ardından enter tuşuna basın):

komut-satırı

>>> Post.objects.filter(published_date__lte=timezone.now())
[<Post: Harika bir gönderi>]

Nesneleri Sıralama

QuerySets ayrıca nesne listesini sıralamanızı da sağlar. Nesneleri created_date (yaratilma_tarihi) özelliğine göre sıralamayı deneyelim:

komut-satırı

>>> Post.objects.order_by('created_date')
[<Post: Gönderi 1>, <Post: Gönderi 2>, <Post: Harika bir gönderi>, <Post: Nefis bir gönderi>]

Başına - ekleyerek sıralamayı tersine de çevirebiliriz:

komut-satırı

>>> Post.objects.order_by('-created_date')
[<Post: Nefis bir gönderi>, <Post: Harika bir gönderi>, <Post: Gönderi 2>, <Post: Gönderi 1>]>

QuerySets (SorguSetlerini) Zincirlemek (Chaining)

Sorgu setlerini zincirleyerek beraber kullanabilirsiniz:

>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
<QuerySet [<Post: Gönderi 2>, <Post:Harika bir gönderi!>, <Post: Nefis bir gönderi>, <Post: Gönderi 1>]>

Zincirleme gerçekten çok güçlüdür ve oldukça karmaşık sorgular yazmanıza imkan sağlar.

Güzel! Şimdi bir sonraki bölüm için hazırız. Komut satırını kapatmak için, şunu yazalım:

komut-satırı

>>> exit()
$

results matching ""

    No results matching ""