Django’da CRUD İşlemleri ve Model İlişkileri (OneToOne, ForeignKey, ManyToMany) Uygulamalı Rehber
Django’da CRUD işlemleri (Create, Read, Update, Delete) ile birlikte ilişki türlerini (OneToOne, ForeignKey, ManyToMany) öğreten kapsamlı bir eğitim hazırlayabiliriz. Bu proje:
📚 “Okul Kulüp Yönetim Sistemi”
Bu sistemde:
Öğrenciler olacak
Öğrencilerin profili olacak
Öğrenciler kulüplere katılacak
Böylece:
| İlişki | Django Alanı | Örnek |
|---|---|---|
| Bire Bir | OneToOneField | Öğrenci → Öğrenci Profili |
| Bire Çok | ForeignKey | Öğretmen → Öğrenciler |
| Çoka Çok | ManyToManyField | Öğrenci ↔ Kulüpler |
Aynı zamanda CRUD işlemleri yapılacak.
Django CRUD + İlişkiler Eğitim Projesi
1️⃣ Proje Oluşturma
django-admin startproject okul
cd okul
python manage.py startapp yonetim
settings.py
INSTALLED_APPS = [
'yonetim',
]
2️⃣ Model Tasarımı (İlişkiler)
models.py
from django.db import models
class Ogretmen(models.Model):
ad = models.CharField(max_length=50)
soyad = models.CharField(max_length=50)
def __str__(self):
return f"{self.ad} {self.soyad}"
class Ogrenci(models.Model):
ad = models.CharField(max_length=50)
soyad = models.CharField(max_length=50)
ogretmen = models.ForeignKey(
Ogretmen,
on_delete=models.CASCADE,
related_name="ogrenciler"
)
def __str__(self):
return f"{self.ad} {self.soyad}"
class Profil(models.Model):
ogrenci = models.OneToOneField(
Ogrenci,
on_delete=models.CASCADE
)
dogum_tarihi = models.DateField()
sehir = models.CharField(max_length=100)
def __str__(self):
return f"{self.ogrenci.ad} Profil"
class Kulup(models.Model):
ad = models.CharField(max_length=100)
ogrenciler = models.ManyToManyField(Ogrenci)
def __str__(self):
return self.ad
3️⃣ İlişki Diyagramı
Ogretmen
│
│ (1 → N)
▼
Ogrenci
│
│ (1 → 1)
▼
Profil
Ogrenci
▲
│ (N ↔ N)
│
Kulup
4️⃣ Migration
python manage.py makemigrations
python manage.py migrate
5️⃣ Admin Panel
admin.py
from django.contrib import admin
from .models import Ogretmen, Ogrenci, Profil, Kulup
admin.site.register(Ogretmen)
admin.site.register(Ogrenci)
admin.site.register(Profil)
admin.site.register(Kulup)
6️⃣ CRUD İşlemleri
CREATE (Kayıt Ekleme)
views.py
from django.shortcuts import render, redirect
from .models import Ogrenci
from .forms import OgrenciForm
def ogrenci_ekle(request):
form = OgrenciForm(request.POST or None)
if form.is_valid():
form.save()
return redirect("ogrenci_list")
return render(request,"ogrenci_ekle.html",{"form":form})
READ (Listeleme)
def ogrenci_list(request):
ogrenciler = Ogrenci.objects.all()
return render(request,"ogrenci_list.html",{
"ogrenciler":ogrenciler
})
UPDATE (Güncelleme)
def ogrenci_guncelle(request,id):
ogrenci = Ogrenci.objects.get(id=id)
form = OgrenciForm(
request.POST or None,
instance=ogrenci
)
if form.is_valid():
form.save()
return redirect("ogrenci_list")
return render(request,"ogrenci_ekle.html",{"form":form})
DELETE (Silme)
def ogrenci_sil(request,id):
ogrenci = Ogrenci.objects.get(id=id)
ogrenci.delete()
return redirect("ogrenci_list")
7️⃣ Form
forms.py
from django import forms
from .models import Ogrenci
class OgrenciForm(forms.ModelForm):
class Meta:
model = Ogrenci
fields = "__all__"
8️⃣ URL Tanımları
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("ogrenciler/",views.ogrenci_list,name="ogrenci_list"),
path("ogrenci-ekle/",views.ogrenci_ekle,name="ogrenci_ekle"),
path("ogrenci-guncelle/<int:id>/",
views.ogrenci_guncelle,
name="ogrenci_guncelle"),
path("ogrenci-sil/<int:id>/",
views.ogrenci_sil,
name="ogrenci_sil"),
]
9️⃣ Template (Liste)
<h1>Öğrenciler</h1>
<a href="{% url 'ogrenci_ekle' %}">Yeni Öğrenci</a>
<ul>
{% for ogrenci in ogrenciler %}
<li>
{{ ogrenci.ad }} {{ ogrenci.soyad }}
<a href="{% url 'ogrenci_guncelle' ogrenci.id %}">Düzenle</a>
<a href="{% url 'ogrenci_sil' ogrenci.id %}">Sil</a>
</li>
{% endfor %}
</ul>
ogrenci_ekle.html dosyasını da tamamlayalım. Bu sayfa öğrenci ekleme ve güncelleme (CREATE + UPDATE) işlemlerinde kullanılan form sayfasıdır.
📄 ogrenci_ekle.html
Kaynak Kod: https://github.com/nuritiras/okulyonetim.git
10️⃣ ManyToMany Kullanımı
Bir öğrencinin kulüplerini görmek:
ogrenci = Ogrenci.objects.get(id=1)
ogrenci.kulup_set.all()
Bir kulüpteki öğrenciler:
kulup = Kulup.objects.get(id=1)
kulup.ogrenciler.all()
11️⃣ ORM Sorgu Örnekleri
Öğretmenin öğrencileri
ogretmen = Ogretmen.objects.get(id=1)
ogretmen.ogrenciler.all()
Öğrencinin öğretmeni
ogrenci.ogretmen
Öğrencinin profili
ogrenci.profil
Öğrendiğin Django Konuları
Bu uygulamada:
✅ Model tasarımı
✅ CRUD işlemleri
✅ Django ORM
✅ OneToOneField
✅ ForeignKey
✅ ManyToManyField
✅ ModelForm
✅ Template
✅ URL routing
öğrenilmiş olur.
Ek Bilgi:
Django’da related_name, ilişkili model üzerinden ters (reverse) sorgu yapabilmemizi sağlayan isimdir.
Senin örneğindeki model şöyleydi:
class Ogrenci(models.Model):
ad = models.CharField(max_length=50)
soyad = models.CharField(max_length=50)
ogretmen = models.ForeignKey(
Ogretmen,
on_delete=models.CASCADE,
related_name="ogrenciler"
)
Burada:
OgrencimodeliOgretmenmodeline ForeignKey ile bağlıdır
Yani ilişki:
Ogretmen (1) ------> (N) Ogrenci
Bir öğretmenin birden fazla öğrencisi olabilir.
1️⃣ related_name Olmadan
Eğer related_name yazmazsan Django otomatik isim üretir.
ogretmen.ogrenci_set.all()
Örnek:
ogretmen = Ogretmen.objects.get(id=1)
ogretmen.ogrenci_set.all()
Bu öğretmenin tüm öğrencilerini getirir.
Ama bu isim:
ogrenci_set
çok okunaklı değildir.
2️⃣ related_name Kullanırsak
related_name="ogrenciler"
yazarsak artık şöyle erişebiliriz:
ogretmen.ogrenciler.all()
Örnek:
ogretmen = Ogretmen.objects.get(id=1)
ogrenciler = ogretmen.ogrenciler.all()
Bu daha anlaşılır ve profesyonel bir kullanımdır.
3️⃣ Mantık Diyagramı
Ogretmen
│
│ ForeignKey
▼
Ogrenci
Normalde Django:
ogretmen.ogrenci_set
oluşturur.
Ama related_name yazarsak:
ogretmen.ogrenciler
oluşturur.
4️⃣ İki Yönlü Erişim
Öğrenciden öğretmene gitmek
ogrenci.ogretmen
Öğretmenden öğrencilere gitmek
ogretmen.ogrenciler.all()
5️⃣ Django ORM Mantığı
| Nereden | Nereye | Kod |
|---|---|---|
| Öğrenci → Öğretmen | FK | ogrenci.ogretmen |
| Öğretmen → Öğrenciler | related_name | ogretmen.ogrenciler.all() |
6️⃣ Neden Çok Önemli?
Büyük projelerde related_name kullanmazsan:
comment_set
post_set
user_set
gibi karışık isimler oluşur.
Profesyonel Django projelerinde genelde:
related_name="ogrenciler"
related_name="yorumlar"
related_name="siparisler"
gibi anlamlı isimler kullanılır.
Django ORM’de ilişkilerle en çok kullanılan sorguları bilmek çok önemlidir. Özellikle ForeignKey, OneToOne ve ManyToMany ilişkilerinde performanslı sorgular yazmayı sağlar.
Aşağıda sana en önemli 15 Django ORM ilişki sorgusunu basit örneklerle hazırladım.
Örnek modeller:
class Ogretmen(models.Model):
ad = models.CharField(max_length=50)
class Ogrenci(models.Model):
ad = models.CharField(max_length=50)
ogretmen = models.ForeignKey(
Ogretmen,
on_delete=models.CASCADE,
related_name="ogrenciler"
)
class Kulup(models.Model):
ad = models.CharField(max_length=100)
ogrenciler = models.ManyToManyField(Ogrenci)
1️⃣ Tüm kayıtları getirme
Ogrenci.objects.all()
Veritabanındaki tüm öğrencileri getirir.
2️⃣ ID ile kayıt getirme
Ogrenci.objects.get(id=1)
Tek bir kayıt döndürür.
3️⃣ Filtreleme
Ogrenci.objects.filter(ad="Ahmet")
Adı Ahmet olan öğrencileri getirir.
4️⃣ ForeignKey üzerinden filtreleme
Ogrenci.objects.filter(ogretmen__ad="Ali")
Öğretmeni Ali olan öğrencileri getirir.
Burada:
ogretmen__ad
şu anlama gelir:
Ogrenci → Ogretmen → ad
5️⃣ related_name ile erişim
ogretmen = Ogretmen.objects.get(id=1)
ogretmen.ogrenciler.all()
Bir öğretmenin tüm öğrencilerini getirir.
6️⃣ ManyToMany ilişkisi sorgulama
kulup = Kulup.objects.get(id=1)
kulup.ogrenciler.all()
Kulüpteki tüm öğrenciler.
7️⃣ Öğrencinin kulüpleri
ogrenci.kulup_set.all()
Öğrencinin katıldığı kulüpler.
8️⃣ contains arama
Ogrenci.objects.filter(ad__contains="ah")
İçinde "ah" geçen isimler
9️⃣ icontains (büyük küçük harf duyarsız)
Ogrenci.objects.filter(ad__icontains="ah")
Ahmet
AHMET
ahmet
hepsini bulur.
🔟 order_by (sıralama)
Ogrenci.objects.order_by("ad")
Ada göre sıralar.
Ters sıralama:
Ogrenci.objects.order_by("-ad")
1️⃣1️⃣ count()
Ogrenci.objects.count()
Toplam öğrenci sayısı.
1️⃣2️⃣ exists()
Ogrenci.objects.filter(ad="Ahmet").exists()
Kayıt var mı kontrol eder.
1️⃣3️⃣ select_related (performans)
ForeignKey ilişkilerinde kullanılır.
Ogrenci.objects.select_related("ogretmen")
Bu sayede:
Ogrenci → Ogretmen
tek SQL sorgusunda gelir.
Normalde:
N + 1 query problemi
oluşabilir.
1️⃣4️⃣ prefetch_related
ManyToMany ilişkilerinde kullanılır.
Kulup.objects.prefetch_related("ogrenciler")
Kulüp ve öğrencileri tek sorgu ile optimize eder.
1️⃣5️⃣ annotate (hesaplama)
Öğretmenin kaç öğrencisi var?
from django.db.models import Count
Ogretmen.objects.annotate(
ogrenci_sayisi=Count("ogrenciler")
)
Sonuç:
Ali → 5 öğrenci
Veli → 3 öğrenci
Django ORM İlişki Mantığı Diyagramı
Ogretmen
│
│ ForeignKey
▼
Ogrenci
▲
│
ManyToMany
│
Kulup
Profesyonel Django Geliştiricilerin En Çok Kullandığı 5 ORM
| ORM | Amaç |
|---|---|
| filter | veri filtreleme |
| select_related | FK performansı |
| prefetch_related | ManyToMany performansı |
| annotate | veri hesaplama |
| aggregate | toplam veri |
🚀 Django ORM’de En Kritik Konu
N+1 Query Problemi ve ORM Performans Optimizasyonu
Bu konu:
Orta seviye Django geliştiriciyi
Profesyonel Django geliştiriciden ayıran konudur.
Yorumlar
Yorum Gönder