{"id":34409,"date":"2025-11-16T09:31:05","date_gmt":"2025-11-16T06:31:05","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/"},"modified":"2025-11-16T09:31:05","modified_gmt":"2025-11-16T06:31:05","slug":"django-many-to-many-iliskilerde-araci-modellerin-gucu","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/","title":{"rendered":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc"},"content":{"rendered":"<p>Django&#8217;da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla <mark><code>through<\/code> modelleri<\/mark> devreye girer. Bu makale, Django&#8217;da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.<\/p>\n<p>Django, model tan\u0131mlamalar\u0131n\u0131zda bir <mark><code>ManyToManyField<\/code><\/mark> kulland\u0131\u011f\u0131n\u0131zda, iki model aras\u0131nda otomatik olarak bir ba\u011flay\u0131c\u0131 tablo (intermediate table) olu\u015fturur. Bu tablo, her iki modelin birincil anahtarlar\u0131n\u0131 (primary keys) i\u00e7erir ve aralar\u0131ndaki ili\u015fkiyi y\u00f6netir. \u00d6rne\u011fin, bir \u00f6\u011frencinin birden fazla derse kay\u0131t olabilece\u011fi ve bir dersin birden fazla \u00f6\u011frenciye sahip olabilece\u011fi bir okul sistemini d\u00fc\u015f\u00fcnelim. Bu senaryoda <mark><code>Student<\/code><\/mark> ve <mark><code>Course<\/code><\/mark> modelleri aras\u0131nda do\u011frudan bir <mark><code>ManyToManyField<\/code><\/mark> tan\u0131mlamak olduk\u00e7a kolayd\u0131r ve Django, aradaki ili\u015fkiyi sorunsuz bir \u015fekilde y\u00f6netir.<\/p>\n<p>Peki ya bu ili\u015fkinin kendisi hakk\u0131nda ek bilgi depolamak istersek ne olur? Mesela, \u00f6\u011frencinin derse hangi tarihte kaydoldu\u011funu, dersten ald\u0131\u011f\u0131 notu veya dersteki kat\u0131l\u0131m durumunu bu ili\u015fki \u00fczerinde tutmak istiyoruz. Django&#8217;nun otomatik olarak olu\u015fturdu\u011fu ba\u011flay\u0131c\u0131 tablo, sadece ili\u015fkiyi kurmak i\u00e7in gerekli olan anahtarlar\u0131 i\u00e7erir ve bu t\u00fcrden ek verileri saklamak i\u00e7in uygun bir yer sa\u011flamaz. \u0130\u015fte bu durumda, Django&#8217;nun sundu\u011fu <mark>arac\u0131 model<\/mark> (intermediate model) veya yayg\u0131n bilinen ad\u0131yla <mark><code>through<\/code> modeli<\/mark> kavram\u0131 devreye girer. Bu \u00f6zel model, iki ana model aras\u0131ndaki ili\u015fkiyi temsil eden ve bu ili\u015fkiyle ilgili t\u00fcm ek verileri depolayan ayr\u0131 bir veritaban\u0131 tablosu g\u00f6revi g\u00f6r\u00fcr. Bu yakla\u015f\u0131m, sadece veritaban\u0131 tasar\u0131m\u0131n\u0131z\u0131 daha esnek hale getirmekle kalmaz, ayn\u0131 zamanda uygulaman\u0131z\u0131n i\u015f mant\u0131\u011f\u0131n\u0131 da zenginle\u015ftirmenize olanak tan\u0131r. Dolay\u0131s\u0131yla, standart <mark><code>ManyToManyField<\/code><\/mark>&#8216;nin \u00f6tesine ge\u00e7erek, ili\u015fkilerinizin derinliklerine inmek ve onlara anlam katmak istedi\u011finizde arac\u0131 modeller vazge\u00e7ilmez bir ara\u00e7 haline gelir.<\/p>\n<p>\u00d6rnek verecek olursak, bir e-ticaret uygulamas\u0131nda bir <mark><code>Product<\/code><\/mark> modelimiz ve bir <mark><code>Category<\/code><\/mark> modelimiz olsun. Bir \u00fcr\u00fcn birden fazla kategoriye ait olabilir ve bir kategori birden fazla \u00fcr\u00fcn i\u00e7erebilir. Bu do\u011frudan bir <mark><code>ManyToManyField<\/code><\/mark> senaryosudur. Ancak, \u00fcr\u00fcn\u00fcn kategoriye eklenme tarihi, o kategori i\u00e7indeki g\u00f6sterim s\u0131ras\u0131 veya kategorideki pop\u00fclarite puan\u0131 gibi meta verileri depolamak istedi\u011fimizde, bu basit ili\u015fki yeterli olmaz. \u0130\u015fte bu noktada, <mark><code>ProductCategory<\/code><\/mark> ad\u0131nda bir arac\u0131 model olu\u015fturarak, <mark><code>Product<\/code><\/mark> ve <mark><code>Category<\/code><\/mark> modelleri aras\u0131ndaki ili\u015fkiyi detayland\u0131rabiliriz. Bu, uygulaman\u0131z\u0131n veri modelini daha g\u00fc\u00e7l\u00fc ve i\u015flevsel hale getirmenin temel ad\u0131mlar\u0131ndan biridir.<\/p>\n<h2 id=\"temel-kavramlar\">\u00c7oktan \u00c7o\u011fa \u0130li\u015fkiler ve Django&#8217;nun Varsay\u0131lan Yakla\u015f\u0131m\u0131<\/h2>\n<p>\u00c7oktan \u00e7o\u011fa ili\u015fkiler, veritaban\u0131 tasar\u0131m\u0131nda s\u0131kl\u0131kla kar\u015f\u0131la\u015f\u0131lan bir durumdur. \u0130ki varl\u0131k t\u00fcr\u00fc aras\u0131nda, bir varl\u0131\u011f\u0131n birden fazla di\u011fer varl\u0131kla ili\u015fkili olabilece\u011fi ve di\u011fer varl\u0131\u011f\u0131n da birden fazla ilk varl\u0131kla ili\u015fkili olabilece\u011fi anlam\u0131na gelir. Klasik \u00f6rneklerden biri <mark><code>Yazar<\/code><\/mark> ve <mark><code>Kitap<\/code><\/mark> modelleri aras\u0131ndaki ili\u015fkidir. Bir yazar birden fazla kitap yazabilir ve bir kitap birden fazla yazar taraf\u0131ndan yaz\u0131lm\u0131\u015f olabilir. Django&#8217;da bu t\u00fcr bir ili\u015fkiyi tan\u0131mlamak i\u00e7in <mark><code>ManyToManyField<\/code><\/mark> kullan\u0131l\u0131r. \u00d6rne\u011fin:<\/p>\n<pre><code class=\"language-python\">\n# models.py\n\nfrom django.db import models\n\nclass Yazar(models.Model):\n    isim = models.CharField(max_length=100)\n    # ... di\u011fer alanlar ...\n\n    def __str__(self):\n        return self.isim\n\nclass Kitap(models.Model):\n    baslik = models.CharField(max_length=200)\n    yazarlar = models.ManyToManyField(Yazar) # Burada ManyToManyField kullan\u0131ld\u0131\n    # ... di\u011fer alanlar ...\n\n    def __str__(self):\n        return self.baslik\n\n<\/pre>\n<p><\/code><\/p>\n<p>Bu tan\u0131m ile Django, arka planda otomatik olarak <mark><code>app_kitap_yazarlar<\/code><\/mark> (veya benzeri bir isimle) ad\u0131nda bir ba\u011flay\u0131c\u0131 tablo olu\u015fturur. Bu tablo genellikle sadece iki s\u00fctun i\u00e7erir: <mark><code>kitap_id<\/code><\/mark> ve <mark><code>yazar_id<\/code><\/mark>. Bu s\u00fctunlar, ilgili <mark><code>Kitap<\/code><\/mark> ve <mark><code>Yazar<\/code><\/mark> modellerinin birincil anahtarlar\u0131n\u0131 tutar. Bu yap\u0131, hangi kitab\u0131n hangi yazar(lar)a ait oldu\u011funu ve hangi yazar\u0131n hangi kitap(lar)\u0131 yazd\u0131\u011f\u0131n\u0131 takip etmek i\u00e7in yeterlidir.<\/p>\n<p>Ancak, bu varsay\u0131lan yakla\u015f\u0131m\u0131n baz\u0131 s\u0131n\u0131rlamalar\u0131 vard\u0131r. Diyelim ki, bir yazar\u0131n belirli bir kitaptaki <mark>rol\u00fcn\u00fc<\/mark> (\u00f6rne\u011fin \"Ba\u015f Yazar\", \"Yard\u0131mc\u0131 Yazar\") veya o kitap i\u00e7in ne kadar telif hakk\u0131 ald\u0131\u011f\u0131n\u0131 saklamak istiyoruz. Bu t\u00fcr bilgiler, do\u011frudan ne <mark><code>Yazar<\/code><\/mark> modeline ne de <mark><code>Kitap<\/code><\/mark> modeline aittir; bunlar ili\u015fkinin kendisine ait verilerdir. Varsay\u0131lan ba\u011flay\u0131c\u0131 tablo, bu t\u00fcr ek s\u00fctunlar\u0131 bar\u0131nd\u0131ramaz \u00e7\u00fcnk\u00fc Django, bu tablonun yap\u0131s\u0131n\u0131 tamamen kendi i\u00e7 mekanizmalar\u0131na g\u00f6re y\u00f6netir. Bu k\u0131s\u0131tlama, ili\u015fkilerinizin yaln\u0131zca var olup olmad\u0131\u011f\u0131n\u0131 de\u011fil, ayn\u0131 zamanda o ili\u015fkinin <mark>niteliklerini<\/mark> de depolaman\u0131z gerekti\u011finde ortaya \u00e7\u0131kar. \u0130\u015fte bu noktada, varsay\u0131lan <mark><code>ManyToManyField<\/code><\/mark> yetersiz kal\u0131r ve Django'nun <mark>arac\u0131 model<\/mark> mekanizmas\u0131n\u0131 kullanma ihtiyac\u0131 do\u011far. Arac\u0131 model sayesinde, bu ili\u015fki tablosunu kendimiz tan\u0131mlayabilir ve istedi\u011fimiz kadar ek alan ekleyerek ili\u015fkiyi zenginle\u015ftirebiliriz. Bu esneklik, karma\u015f\u0131k i\u015f gereksinimlerini kar\u015f\u0131lamak ve daha detayl\u0131 veri modelleri olu\u015fturmak i\u00e7in kritik bir \u00f6neme sahiptir.<\/p>\n<div class=\"info-box\">\n  Uzman \u0130pucu: \u00c7oktan \u00e7o\u011fa ili\u015fkiniz basit bir ba\u011flamdan \u00f6teye ge\u00e7iyorsa, yani ili\u015fkinin kendisi hakk\u0131nda bilgi depolaman\u0131z gerekiyorsa, mutlaka arac\u0131 model kullanmay\u0131 d\u00fc\u015f\u00fcn\u00fcn. Bu, gelecekteki esneklik ve \u00f6l\u00e7eklenebilirlik i\u00e7in sa\u011flam bir temel olu\u015fturur.\n<\/div>\n<h2 id=\"araci-modelin-temelleri\">Arac\u0131 Model (Through Model) Nedir ve Nas\u0131l Tan\u0131mlan\u0131r?<\/h2>\n<p>Yukar\u0131da bahsedildi\u011fi gibi, Django'nun otomatik olarak olu\u015fturdu\u011fu ba\u011flay\u0131c\u0131 tabloya ek veri ekleyemeyiz. Bu k\u0131s\u0131tlamay\u0131 a\u015fmak i\u00e7in, ili\u015fkiyi temsil eden <mark>kendi \u00f6zel modelimizi<\/mark> olu\u015fturabiliriz. \u0130\u015fte bu \u00f6zel modele <mark>arac\u0131 model (intermediate model)<\/mark> veya <mark><code>through<\/code> modeli<\/mark> denir. Bu model, iki ana model aras\u0131na yerle\u015fir ve ikisi aras\u0131ndaki her bir benzersiz ili\u015fki i\u00e7in bir kay\u0131t tutar, ayn\u0131 zamanda bu ili\u015fkinin kendine \u00f6zg\u00fc ek niteliklerini de bar\u0131nd\u0131r\u0131r.<\/p>\n<p>Bir arac\u0131 model tan\u0131mlaman\u0131n temel ad\u0131mlar\u0131 \u015funlard\u0131r:<\/p>\n<ol>\n<li>\u0130li\u015fkiyi temsil edecek yeni bir Django modeli olu\u015fturun.<\/li>\n<li>Bu yeni modelin, ili\u015fkideki her iki ana modele de <mark><code>ForeignKey<\/code><\/mark> ile ba\u011flanmas\u0131n\u0131 sa\u011flay\u0131n.<\/li>\n<li><mark><code>ManyToManyField<\/code><\/mark> tan\u0131mlarken, <mark><code>through<\/code><\/mark> parametresini kullanarak olu\u015fturdu\u011funuz arac\u0131 modeli i\u015faret edin.<\/li>\n<\/ol>\n<p>\u015eimdi, <mark><code>Student<\/code><\/mark> ve <mark><code>Course<\/code><\/mark> modelleri aras\u0131ndaki ili\u015fkiyi, \u00f6\u011frencinin derse kay\u0131t tarihini ve notunu da saklayacak \u015fekilde bir arac\u0131 model ile nas\u0131l tan\u0131mlayaca\u011f\u0131m\u0131za bakal\u0131m:<\/p>\n<pre><code class=\"language-python\">\n# models.py\n\nfrom django.db import models\nfrom django.utils import timezone\n\nclass Ogrenci(models.Model):\n    ad = models.CharField(max_length=100)\n    soyad = models.CharField(max_length=100)\n    email = models.EmailField(unique=True)\n\n    def __str__(self):\n        return f\"{self.ad} {self.soyad}\"\n\nclass Ders(models.Model):\n    isim = models.CharField(max_length=100)\n    kodu = models.CharField(max_length=10, unique=True)\n    # Bir dersin bir\u00e7ok \u00f6\u011frencisi olabilir ve bir \u00f6\u011frenci bir\u00e7ok derse kay\u0131t olabilir.\n    # Bu ili\u015fkiyi Kayit modeli \u00fczerinden kuraca\u011f\u0131z.\n    ogrenciler = models.ManyToManyField(Ogrenci, through='Kayit', related_name='dersler')\n\n    def __str__(self):\n        return self.isim\n\nclass Kayit(models.Model): # Arac\u0131 (Through) Modelimiz\n    ogrenci = models.ForeignKey(Ogrenci, on_delete=models.CASCADE)\n    ders = models.ForeignKey(Ders, on_delete=models.CASCADE)\n    kayit_tarihi = models.DateTimeField(default=timezone.now)\n    notu = models.DecimalField(max_digits=4, decimal_places=2, null=True, blank=True)\n\n    class Meta:\n        # Bir \u00f6\u011frencinin ayn\u0131 derse birden fazla kay\u0131t olmas\u0131n\u0131 engellemek i\u00e7in\n        unique_together = ('ogrenci', 'ders')\n        verbose_name = \"Ders Kayd\u0131\"\n        verbose_name_plural = \"Ders Kay\u0131tlar\u0131\"\n\n    def __str__(self):\n        return f\"{self.ogrenci.ad} {self.ogrenci.soyad} - {self.ders.isim} Kayd\u0131\"\n\n<\/pre>\n<p><\/code><\/p>\n<p>Yukar\u0131daki \u00f6rnekte, <mark><code>Kayit<\/code><\/mark> ad\u0131nda yeni bir model olu\u015fturduk. Bu model, <mark><code>Ogrenci<\/code><\/mark> ve <mark><code>Ders<\/code><\/mark> modellerine birer <mark><code>ForeignKey<\/code><\/mark> ile ba\u011flan\u0131r. Ayr\u0131ca, ili\u015fkinin kendisine ait olan <mark><code>kayit_tarihi<\/code><\/mark> ve <mark><code>notu<\/code><\/mark> alanlar\u0131n\u0131 i\u00e7erir. <mark><code>Ders<\/code><\/mark> modelindeki <mark><code>ManyToManyField<\/code><\/mark> tan\u0131m\u0131nda, <mark><code>through='Kayit'<\/code><\/mark> parametresini kullanarak Django'ya bu ili\u015fkinin <mark><code>Kayit<\/code><\/mark> modeli arac\u0131l\u0131\u011f\u0131yla y\u00f6netilece\u011fini belirtiyoruz. <mark><code>unique_together = ('ogrenci', 'ders')<\/code><\/mark> ifadesi ise, bir \u00f6\u011frencinin ayn\u0131 derse birden fazla kez kay\u0131t olmas\u0131n\u0131 engellemek i\u00e7in bir veritaban\u0131 k\u0131s\u0131tlamas\u0131 ekler, bu da veri tutarl\u0131l\u0131\u011f\u0131 a\u00e7\u0131s\u0131ndan \u00f6nemlidir. Bu yap\u0131land\u0131rma ile art\u0131k her bir \u00f6\u011frenci-ders ili\u015fkisi i\u00e7in <mark>kay\u0131t tarihi<\/mark> ve <mark>not<\/mark> gibi spesifik verileri depolayabilir ve bu veriler \u00fczerinde esnek sorgulamalar yapabiliriz. Arac\u0131 modeller, bu t\u00fcr karma\u015f\u0131k i\u015f kurallar\u0131n\u0131 veri modelinize entegre etmenizi sa\u011flayarak, uygulaman\u0131z\u0131n ger\u00e7ek d\u00fcnya senaryolar\u0131n\u0131 daha do\u011fru yans\u0131tmas\u0131na yard\u0131mc\u0131 olur.<\/p>\n<h2 id=\"gercek-dunya-senaryosu\">Ger\u00e7ek D\u00fcnya Senaryosu: Proje Y\u00f6netimi ve Kullan\u0131c\u0131 Rolleri<\/h2>\n<p>\u015eimdi daha karma\u015f\u0131k ve yayg\u0131n bir ger\u00e7ek d\u00fcnya senaryosu \u00fczerinden arac\u0131 modellerin g\u00fcc\u00fcn\u00fc g\u00f6sterelim: Bir proje y\u00f6netim sistemi. Bu sistemde, kullan\u0131c\u0131lar (User) farkl\u0131 projelere (Project) kat\u0131labilirler. Ancak, bir kullan\u0131c\u0131n\u0131n bir projedeki rol\u00fc (\u00f6rne\u011fin \"Y\u00f6netici\", \"Geli\u015ftirici\", \"G\u00f6r\u00fcnt\u00fcleyici\") projeden projeye de\u011fi\u015fiklik g\u00f6sterebilir. Ayr\u0131ca, kullan\u0131c\u0131n\u0131n projeye ne zaman atand\u0131\u011f\u0131 veya projedeki aktiflik durumu gibi ek bilgiler de tutmak isteyebiliriz. Bu, do\u011frudan bir <mark><code>ManyToManyField<\/code><\/mark> ile \u00e7\u00f6z\u00fclemeyecek bir durumdur.<\/p>\n<p>Bu senaryoyu \u00e7\u00f6zmek i\u00e7in, <mark><code>Kullanici<\/code><\/mark> ve <mark><code>Proje<\/code><\/mark> modelleri aras\u0131na bir <mark><code>ProjeUyeligi<\/code><\/mark> (ProjectMembership) ad\u0131nda bir arac\u0131 model yerle\u015ftirece\u011fiz.<\/p>\n<pre><code class=\"language-python\">\n# models.py\n\nfrom django.db import models\nfrom django.contrib.auth.models import User # Django'nun varsay\u0131lan User modelini kullan\u0131yoruz\nfrom django.utils import timezone\n\nclass Proje(models.Model):\n    isim = models.CharField(max_length=200)\n    aciklama = models.TextField(blank=True, null=True)\n    baslangic_tarihi = models.DateField(default=timezone.now)\n    bitis_tarihi = models.DateField(null=True, blank=True)\n    \n    # Kullan\u0131c\u0131lar ile ProjeUyeligi modeli \u00fczerinden \u00e7oktan \u00e7o\u011fa ili\u015fki kuruyoruz.\n    uyeler = models.ManyToManyField(User, through='ProjeUyeligi', related_name='projelerim')\n\n    def __str__(self):\n        return self.isim\n\nclass RolSecenekleri(models.TextChoices):\n    YONETICI = 'ADM', 'Y\u00f6netici'\n    GELISTIRICI = 'DEV', 'Geli\u015ftirici'\n    TESTER = 'TST', 'Test Uzman\u0131'\n    IZLEYICI = 'VIE', '\u0130zleyici'\n\nclass ProjeUyeligi(models.Model): # Arac\u0131 Modelimiz\n    user = models.ForeignKey(User, on_delete=models.CASCADE)\n    proje = models.ForeignKey(Proje, on_delete=models.CASCADE)\n    rol = models.CharField(\n        max_length=3,\n        choices=RolSecenekleri.choices,\n        default=RolSecenekleri.GELISTIRICI,\n    )\n    katilma_tarihi = models.DateTimeField(default=timezone.now)\n    aktif_mi = models.BooleanField(default=True)\n\n    class Meta:\n        unique_together = ('user', 'proje') # Bir kullan\u0131c\u0131n\u0131n ayn\u0131 projede sadece bir \u00fcyeli\u011fi olabilir\n        verbose_name = \"Proje \u00dcyeli\u011fi\"\n        verbose_name_plural = \"Proje \u00dcyelikleri\"\n\n    def __str__(self):\n        return f\"{self.user.username} - {self.proje.isim} ({self.get_rol_display()})\"\n\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yap\u0131da, <mark><code>ProjeUyeligi<\/code><\/mark> modeli, <mark><code>User<\/code><\/mark> ve <mark><code>Proje<\/code><\/mark> modelleri aras\u0131ndaki ili\u015fkiyi detayland\u0131r\u0131r. Her bir <mark><code>ProjeUyeligi<\/code><\/mark> nesnesi, belirli bir kullan\u0131c\u0131n\u0131n belirli bir projedeki <mark>rol\u00fcn\u00fc<\/mark>, projeye <mark>kat\u0131lma tarihini<\/mark> ve o projede hala <mark>aktif olup olmad\u0131\u011f\u0131n\u0131<\/mark> tutar. Bu sayede, ayn\u0131 kullan\u0131c\u0131 farkl\u0131 projelerde farkl\u0131 rollerde yer alabilir ve bu rollerin her biri i\u00e7in ayr\u0131 ayr\u0131 ek bilgiler saklanabilir. \u00d6rne\u011fin, bir kullan\u0131c\u0131 hem \"Proje A\"da y\u00f6netici, hem de \"Proje B\"de geli\u015ftirici olabilir. Bu esneklik, ger\u00e7ek d\u00fcnya uygulamalar\u0131n\u0131n karma\u015f\u0131kl\u0131\u011f\u0131n\u0131 modellemede vazge\u00e7ilmezdir. Ayr\u0131ca, <mark><code>RolSecenekleri<\/code><\/mark> s\u0131n\u0131f\u0131 ile rol se\u00e7eneklerini daha d\u00fczenli ve okunabilir bir \u015fekilde tan\u0131mlad\u0131k, bu da kodun bak\u0131m\u0131n\u0131 kolayla\u015ft\u0131r\u0131r ve olas\u0131 yaz\u0131m hatalar\u0131n\u0131 \u00f6nler. <mark><code>unique_together<\/code><\/mark> k\u0131s\u0131tlamas\u0131, bir kullan\u0131c\u0131n\u0131n ayn\u0131 projeye birden fazla kez atanmas\u0131n\u0131 engelleyerek veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc sa\u011flar. Bu t\u00fcr bir yap\u0131, kapsaml\u0131 yetkilendirme mekanizmalar\u0131 olu\u015fturmak ve kullan\u0131c\u0131lar\u0131n projelerdeki etkile\u015fimlerini detayl\u0131 bir \u015fekilde izlemek i\u00e7in g\u00fc\u00e7l\u00fc bir temel sunar.<\/p>\n<h3 id=\"veri-ekleme-ve-sorgulama\">Arac\u0131 Model \u00dczerinden Veri Ekleme, G\u00fcncelleme ve Sorgulama<\/h3>\n<p>Arac\u0131 model kulland\u0131\u011f\u0131n\u0131zda, <mark><code>ManyToManyField<\/code><\/mark> \u00fczerine do\u011frudan <mark><code>add()<\/code><\/mark>, <mark><code>remove()<\/code><\/mark> veya <mark><code>set()<\/code><\/mark> gibi metodlar\u0131 kullanamazs\u0131n\u0131z \u00e7\u00fcnk\u00fc bu metodlar, arac\u0131 modelin ek alanlar\u0131 hakk\u0131nda bilgiye sahip de\u011fildir. Bunun yerine, arac\u0131 modelin kendisini olu\u015fturarak veya sorgulayarak ili\u015fkileri y\u00f6netmeniz gerekir. Bu, ba\u015flang\u0131\u00e7ta biraz daha fazla kod yazmay\u0131 gerektirse de, ili\u015fkiniz \u00fczerindeki kontrol\u00fc tamamen size verir.<\/p>\n<p><strong>Veri Ekleme:<\/strong><\/p>\n<pre><code class=\"language-python\">\n# Python kabu\u011funda (shell) veya bir view i\u00e7inde\n\nfrom django.contrib.auth.models import User\nfrom .models import Proje, ProjeUyeligi, RolSecenekleri\n\n# \u00d6rnek kullan\u0131c\u0131 ve proje olu\u015ftural\u0131m (varsa zaten kullan\u0131r\u0131z)\nuser1, created = User.objects.get_or_create(username='ahmet', email='ahmet@example.com')\nif created:\n    user1.set_password('pass123')\n    user1.save()\n\nuser2, created = User.objects.get_or_create(username='ayse', email='ayse@example.com')\nif created:\n    user2.set_password('pass123')\n    user2.save()\n\nproje1, _ = Proje.objects.get_or_create(isim='E-Ticaret Sitesi', defaults={'aciklama': 'Online sat\u0131\u015f platformu'})\nproje2, _ = Proje.objects.get_or_create(isim='Blog Uygulamas\u0131', defaults={'aciklama': 'Ki\u015fisel blog platformu'})\n\n# Ahmet'i E-Ticaret Sitesi projesine Y\u00f6netici olarak ekleyelim\nuyelik1 = ProjeUyeligi.objects.create(user=user1, proje=proje1, rol=RolSecenekleri.YONETICI)\nprint(f\"Yeni \u00fcyelik olu\u015fturuldu: {uyelik1}\")\n\n# Ay\u015fe'yi E-Ticaret Sitesi projesine Geli\u015ftirici olarak ekleyelim\nuyelik2 = ProjeUyeligi.objects.create(user=user2, proje=proje1, rol=RolSecenekleri.GELISTIRICI)\nprint(f\"Yeni \u00fcyelik olu\u015fturuldu: {uyelik2}\")\n\n# Ahmet'i Blog Uygulamas\u0131 projesine Geli\u015ftirici olarak ekleyelim\nuyelik3 = ProjeUyeligi.objects.create(user=user1, proje=proje2, rol=RolSecenekleri.GELISTIRICI)\nprint(f\"Yeni \u00fcyelik olu\u015fturuldu: {uyelik3}\")\n\n<\/pre>\n<p><\/code><\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi, do\u011frudan <mark><code>proje1.uyeler.add(user1)<\/code><\/mark> yerine <mark><code>ProjeUyeligi<\/code><\/mark> modelini kullanarak ili\u015fkiyi kurduk ve ek alanlar\u0131 (<mark><code>rol<\/code><\/mark>, <mark><code>katilma_tarihi<\/code><\/mark> gibi) tan\u0131mlad\u0131k.<\/p>\n<p><strong>Veri G\u00fcncelleme:<\/strong><\/p>\n<pre><code class=\"language-python\">\n# Ahmet'in E-Ticaret Sitesi projesindeki rol\u00fcn\u00fc g\u00fcncelleyelim\nahmet_proje1_uyeligi = ProjeUyeligi.objects.get(user=user1, proje=proje1)\nahmet_proje1_uyeligi.rol = RolSecenekleri.TESTER\nahmet_proje1_uyeligi.save()\nprint(f\"Ahmet'in rol\u00fc g\u00fcncellendi: {ahmet_proje1_uyeligi}\")\n\n<\/pre>\n<p><\/code><\/p>\n<p><strong>Veri Sorgulama:<\/strong><\/p>\n<p>Arac\u0131 model \u00fczerinden sorgulama yapmak olduk\u00e7a esnektir. \u0130li\u015fkiyi hem ana modellerden hem de arac\u0131 modelin kendisinden sorgulayabilirsiniz.<\/p>\n<pre><code class=\"language-python\">\n# Bir projedeki t\u00fcm \u00fcyeleri ve rollerini listeleme\nprint(f\"\\n{proje1.isim} projesindeki \u00fcyeler:\")\nfor uyelik in ProjeUyeligi.objects.filter(proje=proje1):\n    print(f\"- {uyelik.user.username} ({uyelik.get_rol_display()})\")\n\n# Bir kullan\u0131c\u0131n\u0131n t\u00fcm projelerini ve rollerini listeleme\nprint(f\"\\n{user1.username} kullan\u0131c\u0131s\u0131n\u0131n dahil oldu\u011fu projeler:\")\nfor uyelik in user1.projeyuyeligi_set.all(): # default related_name used here\n    print(f\"- {uyelik.proje.isim} ({uyelik.get_rol_display()})\")\n\n# Alternatif olarak related_name ile:\nprint(f\"\\n{user1.username} kullan\u0131c\u0131s\u0131n\u0131n dahil oldu\u011fu projeler (related_name ile):\")\nfor uyelik in user1.projelerim.all(): # user modelindeki related_name 'projelerim' idi\n    print(f\"- {uyelik.isim} projesinde {uyelik.projeuyeligi_set.get(user=user1, proje=uyelik).get_rol_display()} rol\u00fc\")\n\n# Sadece belirli bir role sahip \u00fcyeleri filtreleme\nyoneticiler = ProjeUyeligi.objects.filter(proje=proje1, rol=RolSecenekleri.YONETICI)\nprint(f\"\\n{proje1.isim} projesindeki y\u00f6neticiler:\")\nfor uyelik in yoneticiler:\n    print(f\"- {uyelik.user.username}\")\n\n# Geli\u015ftirici rol\u00fcndeki kullan\u0131c\u0131lar\u0131 i\u00e7eren projeleri bulma\ngelistirici_projeleri = Proje.objects.filter(projeuyeligi__rol=RolSecenekleri.GELISTIRICI).distinct()\nprint(\"\\nGeli\u015ftiricisi olan projeler:\")\nfor proje in gelistirici_projeleri:\n    print(f\"- {proje.isim}\")\n\n<\/pre>\n<p><\/code><\/p>\n<p>Bu \u00f6rneklerde, ili\u015fkili verilere eri\u015fmek i\u00e7in <mark><code>_set<\/code><\/mark> veya <mark><code>related_name<\/code><\/mark> niteli\u011fini kullanarak <mark><code>ProjeUyeligi<\/code><\/mark> modeline ula\u015ft\u0131\u011f\u0131m\u0131z\u0131 ve ard\u0131ndan bu modelin alanlar\u0131 \u00fczerinden filtreleme yapt\u0131\u011f\u0131m\u0131z\u0131 g\u00f6rebilirsiniz. Bu y\u00f6ntem, ili\u015fkilerinizin \u00fczerindeki kontrol\u00fc art\u0131r\u0131r ve karma\u015f\u0131k sorgular\u0131 m\u00fcmk\u00fcn k\u0131lar.<\/p>\n<h2 id=\"ileri-duzey-konular\">\u0130leri D\u00fczey Konular ve En \u0130yi Uygulamalar<\/h2>\n<p>Arac\u0131 modellerin temel kullan\u0131m\u0131 olduk\u00e7a basittir, ancak Django ekosisteminde bu modelleri daha g\u00fc\u00e7l\u00fc ve verimli hale getirecek ileri d\u00fczey teknikler ve en iyi uygulamalar da mevcuttur.<\/p>\n<h3 id=\"custom-manager-for-through-model\">Arac\u0131 Model i\u00e7in \u00d6zel Y\u00f6netici (Custom Manager)<\/h3>\n<p>S\u0131k\u00e7a tekrarlanan sorgular\u0131 basitle\u015ftirmek ve kod tekrar\u0131n\u0131 azaltmak i\u00e7in arac\u0131 modelinize \u00f6zel bir y\u00f6netici (manager) ekleyebilirsiniz. \u00d6rne\u011fin, belirli bir projedeki aktif \u00fcyeleri veya belirli bir kullan\u0131c\u0131n\u0131n y\u00f6neticisi oldu\u011fu projeleri d\u00f6nd\u00fcren y\u00f6ntemler ekleyebiliriz.<\/p>\n<pre><code class=\"language-python\">\n# models.py i\u00e7indeki ProjeUyeligi modelinin alt\u0131na ekleyebilirsiniz\n\nclass ProjeUyeligiManager(models.Manager):\n    def aktif_uyeler(self, proje_id):\n        return self.filter(proje__id=proje_id, aktif_mi=True)\n\n    def kullanicinin_yonettigi_projeler(self, user):\n        return self.filter(user=user, rol=RolSecenekleri.YONETICI).select_related('proje')\n\n# ProjeUyeligi modelini g\u00fcncelleyin:\nclass ProjeUyeligi(models.Model):\n    # ... mevcut alanlar ...\n    objects = ProjeUyeligiManager() # \u00d6zel y\u00f6neticiyi at\u0131yoruz\n\n<\/pre>\n<p><\/code><\/p>\n<p>\u015eimdi, bu \u00f6zel y\u00f6neticiyi kullanarak sorgu yapabiliriz:<\/p>\n<pre><code class=\"language-python\">\n# Shell veya view i\u00e7inde\nfrom .models import ProjeUyeligi, User\n\n# E-Ticaret Sitesi projesinin ID'sini alal\u0131m (\u00f6rne\u011fin 1)\nproje_id = Proje.objects.get(isim='E-Ticaret Sitesi').id\n\naktif_uyeler = ProjeUyeligi.objects.aktif_uyeler(proje_id)\nprint(f\"\\nProje ID {proje_id}'deki aktif \u00fcyeler:\")\nfor uyelik in aktif_uyeler:\n    print(f\"- {uyelik.user.username} ({uyelik.get_rol_display()})\")\n\n# Ahmet'in y\u00f6netti\u011fi projeler\nahmet = User.objects.get(username='ahmet')\nahmet_yonettigi_projeler = ProjeUyeligi.objects.kullanicinin_yonettigi_projeler(ahmet)\nprint(f\"\\n{ahmet.username}'in y\u00f6netti\u011fi projeler:\")\nfor uyelik in ahmet_yonettigi_projeler:\n    print(f\"- {uyelik.proje.isim}\")\n\n<\/pre>\n<p><\/code><\/p>\n<h3 id=\"admin-arayuzunde-kullanimi\">Admin Aray\u00fcz\u00fcnde Kullan\u0131m\u0131: Inline Y\u00f6netimi<\/h3>\n<p>Django Admin panelinde arac\u0131 modelleri y\u00f6netmek i\u00e7in <mark><code>TabularInline<\/code><\/mark> veya <mark><code>StackedInline<\/code><\/mark> kullanmak en iyi yoldur. Bu, ana modelin d\u00fczenleme sayfas\u0131nda ili\u015fkili arac\u0131 model kay\u0131tlar\u0131n\u0131 do\u011frudan eklemenize, g\u00fcncellemenize veya silmenize olanak tan\u0131r.<\/p>\n<pre><code class=\"language-python\">\n# admin.py\n\nfrom django.contrib import admin\nfrom .models import Proje, ProjeUyeligi\n\nclass ProjeUyeligiInline(admin.TabularInline): # veya admin.StackedInline\n    model = ProjeUyeligi\n    extra = 1 # Varsay\u0131lan olarak ka\u00e7 bo\u015f form alan\u0131 g\u00f6sterilece\u011fi\n    # Aran\u0131lan kullan\u0131c\u0131 veya proje kolayca bulunabilsin diye raw_id_fields kullanabiliriz\n    raw_id_fields = ('user', 'proje') \n    # Ya da list_display ve search_fields ile daha detayl\u0131 hale getirebiliriz.\n\n@admin.register(Proje)\nclass ProjeAdmin(admin.ModelAdmin):\n    list_display = ('isim', 'baslangic_tarihi', 'bitis_tarihi')\n    search_fields = ('isim', 'aciklama')\n    inlines = [ProjeUyeligiInline] # Inline'\u0131 burada ekliyoruz\n\n# User modelini customize edebiliriz.\n# from django.contrib.auth.admin import UserAdmin as BaseUserAdmin\n# from django.contrib.auth.models import User\n\n# class MyUserAdmin(BaseUserAdmin):\n#     inlines = [ProjeUyeligiInline] # User modeline de ekleyebilirsiniz\n\n# admin.site.unregister(User)\n# admin.site.register(User, MyUserAdmin)\n# ProjeUyeligi modelinin kendisini do\u011frudan admin'de g\u00f6stermek istiyorsan\u0131z:\n@admin.register(ProjeUyeligi)\nclass ProjeUyeligiAdmin(admin.ModelAdmin):\n    list_display = ('user', 'proje', 'rol', 'katilma_tarihi', 'aktif_mi')\n    list_filter = ('rol', 'aktif_mi', 'katilma_tarihi')\n    search_fields = ('user__username', 'proje__isim')\n    raw_id_fields = ('user', 'proje')\n\n<\/pre>\n<p><\/code><\/p>\n<p>Bu yap\u0131land\u0131rma sayesinde, bir <mark><code>Proje<\/code><\/mark> nesnesinin admin sayfas\u0131n\u0131 a\u00e7t\u0131\u011f\u0131n\u0131zda, o projeye ait t\u00fcm <mark><code>ProjeUyeligi<\/code><\/mark> kay\u0131tlar\u0131n\u0131 do\u011frudan g\u00f6rebilecek ve d\u00fczenleyebileceksiniz. Bu, admin panelinden toplu ili\u015fki y\u00f6netimi i\u00e7in olduk\u00e7a kullan\u0131\u015fl\u0131d\u0131r.<\/p>\n<h3 id=\"performans-ipuclari\">Performans \u0130pu\u00e7lar\u0131: Sorgu Optimizasyonu<\/h3>\n<p>Arac\u0131 modellerle \u00e7al\u0131\u015f\u0131rken performans sorunlar\u0131 ya\u015famamak i\u00e7in sorgu optimizasyonuna dikkat etmek \u00f6nemlidir. \u00d6zellikle \u00e7ok say\u0131da kay\u0131tla \u00e7al\u0131\u015f\u0131rken verimli sorgular yazmak uygulaman\u0131z\u0131n h\u0131z\u0131n\u0131 belirleyebilir. <mark><code>select_related()<\/code><\/mark> ve <mark><code>prefetch_related()<\/code><\/mark> metodlar\u0131n\u0131 do\u011fru kullanmak, N+1 sorgu sorununu \u00f6nlemenin anahtar\u0131d\u0131r.<\/p>\n<ul>\n<li><mark><code>select_related()<\/code><\/mark>: <mark><code>ForeignKey<\/code><\/mark> veya <mark><code>OneToOneField<\/code><\/mark> ili\u015fkilerini sorgularken kullan\u0131l\u0131r ve join operasyonu ile ilgili objeleri tek bir SQL sorgusunda getirir.<\/li>\n<li><mark><code>prefetch_related()<\/code><\/mark>: <mark><code>ManyToManyField<\/code><\/mark> veya <mark><code>ReverseForeignKey<\/code><\/mark> ili\u015fkilerini sorgularken kullan\u0131l\u0131r ve ayr\u0131 SQL sorgular\u0131 yaparak sonu\u00e7lar\u0131 Python'da birle\u015ftirir.<\/li>\n<\/ul>\n<pre><code class=\"language-python\">\n# T\u00fcm proje \u00fcyeliklerini ve ilgili kullan\u0131c\u0131\/proje bilgilerini tek seferde getirme\n# ProjeUyeligi -> User (ForeignKey), ProjeUyeligi -> Proje (ForeignKey)\nuyelikler = ProjeUyeligi.objects.select_related('user', 'proje').all()\nfor uyelik in uyelikler:\n    print(f\"{uyelik.user.username} - {uyelik.proje.isim}\") # Bu eri\u015fimler ekstra sorgu \u00e7al\u0131\u015ft\u0131rmaz\n\n# Bir projenin t\u00fcm \u00fcyelerini ve o \u00fcyelerin dahil oldu\u011fu di\u011fer projeleri getirme\n# Bu biraz daha karma\u015f\u0131k bir senaryo. \u00d6nce projenin \u00fcyelerini, sonra her \u00fcyenin projelerini\nproje_obj = Proje.objects.get(isim='E-Ticaret Sitesi')\n# \u00d6nce ProjeUyeligi nesnelerini, sonra ilgili User nesnelerini getirir.\n# Bu a\u015famada user.projelerim'e eri\u015fim hala ekstra sorgu yapar.\nprojeye_ait_uyelikler = ProjeUyeligi.objects.filter(proje=proje_obj).select_related('user')\n\n# Her \u00fcyenin t\u00fcm projelerini prefetch etmek i\u00e7in\n# Bu, user.projelerim'e eri\u015fimlerde N+1 sorununu \u00f6nler.\nprojeye_ait_uyelikler_ve_tum_user_projeleri = ProjeUyeligi.objects \\\n    .filter(proje=proje_obj) \\\n    .select_related('user') \\\n    .prefetch_related('user__projelerim__proje') # user'\u0131n t\u00fcm projelerini ProjeUyeligi \u00fczerinden prefetch et\n\nfor uyelik in projeye_ait_uyelikler_ve_tum_user_projeleri:\n    print(f\"\\n{uyelik.user.username}'in {uyelik.proje.isim} projesindeki rol\u00fc: {uyelik.get_rol_display()}\")\n    print(f\"  {uyelik.user.username}'in t\u00fcm projeleri:\")\n    # user.projelerim'e eri\u015fim art\u0131k prefetch edildi\u011fi i\u00e7in h\u0131zl\u0131d\u0131r\n    for baska_proje_uyeligi in uyelik.user.projelerim.all(): \n        print(f\"    - {baska_proje_uyeligi.isim} (Rol: {baska_proje_uyeligi.projeuyeligi_set.get(user=uyelik.user, proje=baska_proje_uyeligi).get_rol_display()})\")\n\n\n<\/pre>\n<p><\/code><\/p>\n<p>Do\u011fru <mark><code>select_related<\/code><\/mark> ve <mark><code>prefetch_related<\/code><\/mark> kullan\u0131m\u0131yla, arac\u0131 modellerle bile son derece verimli sorgular yazabilir ve uygulaman\u0131z\u0131n performans\u0131n\u0131 \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131rabilirsiniz. Veritaban\u0131 sorgular\u0131n\u0131n say\u0131s\u0131n\u0131 azaltmak, \u00f6zellikle y\u00fcksek trafikli uygulamalarda hayati \u00f6neme sahiptir.<\/p>\n<h2 id=\"mobil-uyumluluk-ipucu\">Mobil Uyumluluk ve Kullan\u0131c\u0131 Deneyimi (Ekstra Not)<\/h2>\n<p>Makalenin ana oda\u011f\u0131 Django modelleri olsa da, bu t\u00fcr ili\u015fkileri y\u00f6neten aray\u00fczlerin (<mark>Django Admin<\/mark> veya \u00f6zel geli\u015ftirdi\u011finiz paneller) mobil uyumlu olmas\u0131, son kullan\u0131c\u0131 deneyimi a\u00e7\u0131s\u0131ndan kritik \u00f6neme sahiptir. \u00d6zellikle \u00e7oktan \u00e7o\u011fa ili\u015fkilerde birden fazla \u00f6\u011fe se\u00e7imi veya arac\u0131 model \u00fczerinden detayl\u0131 veri giri\u015fi s\u00f6z konusu oldu\u011funda, dar ekranlarda kullan\u0131c\u0131lar\u0131n zorlanmamas\u0131 gerekir. Mobil uyumlu formlar, esnek tablolar ve duyarl\u0131 tasar\u0131mlar, bu karma\u015f\u0131k verilerin mobil cihazlarda da rahat\u00e7a y\u00f6netilmesini sa\u011flar.<\/p>\n<p>Web aray\u00fczlerini mobil uyumlu hale getirmek i\u00e7in en yayg\u0131n y\u00f6ntemlerden biri <mark>CSS Media Query<\/mark> kullanmakt\u0131r. Bu sayede, farkl\u0131 ekran geni\u015flikleri i\u00e7in farkl\u0131 stil kurallar\u0131 tan\u0131mlayabilirsiniz. \u00d6rne\u011fin, Django Admin'deki inline formlar\u0131 veya \u00f6zel bir listenin mobil cihazlarda nas\u0131l g\u00f6r\u00fcnece\u011fini ayarlayabilirsiniz:<\/p>\n<pre><code class=\"language-html\">\n<!-- Django Admin veya \u00f6zel template'inize ekleyebilece\u011finiz stil -->\n<style>\n    \/* Genel stil kurallar\u0131 *\/\n    .admin-list-table {\n        width: 100%;\n        border-collapse: collapse;\n    }\n    .admin-list-table th, .admin-list-table td {\n        padding: 8px;\n        border: 1px solid #ddd;\n        text-align: left;\n    }\n\n    \/* Mobil cihazlar i\u00e7in Media Query *\/\n    @media screen and (max-width: 768px) {\n        .admin-list-table {\n            border: 0;\n        }\n        .admin-list-table thead {\n            display: none; \/* Ba\u015fl\u0131k sat\u0131r\u0131n\u0131 gizle *\/\n        }\n        .admin-list-table tr {\n            display: block;\n            margin-bottom: 10px;\n            border: 1px solid #ddd;\n        }\n        .admin-list-table td {\n            display: block;\n            text-align: right;\n            border-bottom: 1px dotted #ddd;\n            position: relative;\n            padding-left: 50%;\n        }\n        .admin-list-table td::before {\n            content: attr(data-label); \/* data-label \u00f6zelli\u011fini kullanarak ba\u015fl\u0131klar\u0131 g\u00f6ster *\/\n            position: absolute;\n            left: 0;\n            width: 45%;\n            padding-left: 10px;\n            font-weight: bold;\n            text-align: left;\n        }\n        \/* Inline form elemanlar\u0131 i\u00e7in *\/\n        .inline-group .form-row {\n            display: block;\n            margin-bottom: 15px;\n        }\n        .inline-group .form-row label {\n            display: block;\n            margin-bottom: 5px;\n            font-weight: bold;\n        }\n        .inline-group .form-row input,\n        .inline-group .form-row select {\n            width: 100%;\n            padding: 8px;\n            box-sizing: border-box;\n        }\n    }\n<\/style>\n\n<!-- HTML tablosu \u00f6rne\u011fi (data-label kullan\u0131m\u0131 i\u00e7in) -->\n<table class=\"admin-list-table\">\n    <thead>\n        <tr>\n            <th>Kullan\u0131c\u0131<\/th>\n            <th>Proje<\/th>\n            <th>Rol<\/th>\n        <\/tr>\n    <\/thead>\n    <tbody>\n        <tr>\n            <td data-label=\"Kullan\u0131c\u0131\">Ahmet<\/td>\n            <td data-label=\"Proje\">E-Ticaret Sitesi<\/td>\n            <td data-label=\"Rol\">Y\u00f6netici<\/td>\n        <\/tr>\n        <tr>\n            <td data-label=\"Kullan\u0131c\u0131\">Ay\u015fe<\/td>\n            <td data-label=\"Proje\">E-Ticaret Sitesi<\/td>\n            <td data-label=\"Rol\">Geli\u015ftirici<\/td>\n        <\/tr>\n    <\/tbody>\n<\/table>\n<\/pre>\n<p><\/code><\/p>\n<p>Bu \u00f6rnek, 768px geni\u015fli\u011fin alt\u0131ndaki ekranlarda tablonun nas\u0131l dikey listeye d\u00f6n\u00fc\u015ft\u00fc\u011f\u00fcn\u00fc ve her h\u00fccrenin kendi ba\u015fl\u0131\u011f\u0131n\u0131 nas\u0131l g\u00f6sterdi\u011fini belirtir. Bu, karma\u015f\u0131k veri tablolar\u0131n\u0131n mobil cihazlarda bile kullan\u0131labilir olmas\u0131n\u0131 sa\u011flar ve Django'da arac\u0131 modellerle y\u00f6netti\u011finiz ili\u015fkisel verilerin her platformda sorunsuz bir deneyim sunmas\u0131na yard\u0131mc\u0131 olur.<\/p>\n<h2 id=\"sonuc\">Sonu\u00e7: Arac\u0131 Modellerin G\u00fcc\u00fc ve Esnekli\u011fi<\/h2>\n<p>Django'da <mark><code>ManyToManyField<\/code><\/mark> ile \u00e7al\u0131\u015f\u0131rken, ili\u015fkilerinizin yaln\u0131zca var olup olmad\u0131\u011f\u0131n\u0131 de\u011fil, ayn\u0131 zamanda bu ili\u015fkilerin kendine \u00f6zg\u00fc niteliklerini de depolaman\u0131z gerekti\u011finde <mark>arac\u0131 modeller<\/mark> (<code>through<\/code> models) vazge\u00e7ilmez bir \u00e7\u00f6z\u00fcm sunar. Bu makalede ele ald\u0131\u011f\u0131m\u0131z gibi, arac\u0131 modeller sayesinde iki ana model aras\u0131ndaki her bir ba\u011f\u0131 ayr\u0131 bir model olarak tan\u0131mlayabilir ve bu ba\u011fa \u00f6zel alanlar ekleyebiliriz. Bu yakla\u015f\u0131m, basit bir \u00f6\u011frenci-ders kayd\u0131ndan karma\u015f\u0131k bir proje y\u00f6netim sistemindeki kullan\u0131c\u0131 rollerine kadar geni\u015f bir yelpazedeki ger\u00e7ek d\u00fcnya senaryolar\u0131n\u0131 modellemenize olanak tan\u0131r.<\/p>\n<p>Arac\u0131 modeller, veri modelinizi daha esnek, anlaml\u0131 ve i\u015f mant\u0131\u011f\u0131n\u0131za uygun hale getirirken, ayn\u0131 zamanda veri tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flamak i\u00e7in <mark><code>unique_together<\/code><\/mark> gibi k\u0131s\u0131tlamalar\u0131 kullanma imkan\u0131 da sunar. Veri ekleme, g\u00fcncelleme ve sorgulama i\u015flemlerinde ba\u015flang\u0131\u00e7ta biraz daha fazla kod yazma ihtiyac\u0131 olsa da, bu artan kontrol, uygulaman\u0131z\u0131n \u00f6l\u00e7eklenebilirli\u011fi ve s\u00fcrd\u00fcr\u00fclebilirli\u011fi a\u00e7\u0131s\u0131ndan uzun vadede \u00f6nemli faydalar sa\u011flar. Ayr\u0131ca, \u00f6zel y\u00f6neticilerle sorgu mant\u0131\u011f\u0131n\u0131z\u0131 basitle\u015ftirmek, Django Admin entegrasyonuyla y\u00f6netimi kolayla\u015ft\u0131rmak ve <mark><code>select_related<\/code><\/mark> \/ <mark><code>prefetch_related<\/code><\/mark> ile performans\u0131 optimize etmek gibi ileri d\u00fczey teknikler, arac\u0131 modellerin potansiyelini tam olarak kullanman\u0131za yard\u0131mc\u0131 olur. Sonu\u00e7 olarak, Django'da ili\u015fkisel verilerinizi zenginle\u015ftirmek ve uygulaman\u0131z\u0131n i\u015f gereksinimlerini eksiksiz kar\u015f\u0131lamak i\u00e7in arac\u0131 modeller, geli\u015ftiricilerin ara\u00e7 kutusundaki en g\u00fc\u00e7l\u00fc ara\u00e7lardan biridir.<\/p>\n<h3 id=\"sikca-sorulan-sorular\">S\u0131k\u00e7a Sorulan Sorular<\/h3>\n<dl>\n<dt><strong>1. Ne zaman arac\u0131 model (through model) kullanmal\u0131y\u0131m?<\/strong><\/dt>\n<dd>\u0130ki model aras\u0131ndaki \u00e7oktan \u00e7o\u011fa ili\u015fkinin kendisine ait ek veri (\u00f6rne\u011fin kay\u0131t tarihi, not, rol, durum) depolaman\u0131z gerekti\u011finde arac\u0131 model kullanmal\u0131s\u0131n\u0131z. E\u011fer sadece iki modelin birbiriyle ili\u015fkili olup olmad\u0131\u011f\u0131n\u0131 bilmek yeterliyse, standart <mark><code>ManyToManyField<\/code><\/mark> kullanmak daha basittir.<\/dd>\n<dt><strong>2. Arac\u0131 model kullanmak performans\u0131 etkiler mi?<\/strong><\/dt>\n<dd>Arac\u0131 model, ekstra bir veritaban\u0131 tablosu ve dolay\u0131s\u0131yla ekstra join i\u015flemleri anlam\u0131na gelir. Bu durum, yanl\u0131\u015f sorgulama stratejileriyle (<mark>N+1 sorgu problemi<\/mark> gibi) performans d\u00fc\u015f\u00fc\u015flerine neden olabilir. Ancak, <mark><code>select_related()<\/code><\/mark> ve <mark><code>prefetch_related()<\/code><\/mark> gibi optimizasyon tekniklerini do\u011fru kullanarak performans \u00fczerindeki olumsuz etkileri minimuma indirebilirsiniz. Genellikle, sa\u011flad\u0131\u011f\u0131 esneklik ve veri zenginli\u011fi, olas\u0131 performans maliyetinden daha a\u011f\u0131r basar.<\/dd>\n<dt><strong>3. Arac\u0131 model olmadan \u00e7oktan \u00e7o\u011fa ili\u015fkide ekstra veri depolayabilir miyim?<\/strong><\/dt>\n<dd>Hay\u0131r, Django'nun standart <mark><code>ManyToManyField<\/code><\/mark> ile olu\u015fturdu\u011fu ba\u011flay\u0131c\u0131 tabloya do\u011frudan ek alanlar ekleyemezsiniz. Bu tablo sadece ili\u015fkideki iki modelin birincil anahtarlar\u0131n\u0131 i\u00e7erir. Ek veri depolamak istiyorsan\u0131z, arac\u0131 model olu\u015fturmak tek yoldur.<\/dd>\n<dt><strong>4. Arac\u0131 model ile <code>ManyToManyField<\/code> aras\u0131ndaki fark nedir?<\/strong><\/dt>\n<dd><mark><code>ManyToManyField<\/code><\/mark>, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa ili\u015fkiyi otomatik olarak kurar ve y\u00f6netir. Arka planda bir ba\u011flay\u0131c\u0131 tablo olu\u015fturur. <mark>Arac\u0131 model<\/mark> ise, <mark><code>ManyToManyField<\/code><\/mark> ile birlikte kullan\u0131lan \u00f6zel bir Django modelidir. <mark><code>ManyToManyField<\/code><\/mark> tan\u0131m\u0131na <mark><code>through='YourThroughModel'<\/code><\/mark> parametresi eklenerek kullan\u0131l\u0131r. Fark, arac\u0131 modelin ili\u015fkinin kendisine ait ek verileri depolaman\u0131za olanak tan\u0131mas\u0131 ve bu ili\u015fkinin y\u00f6netimini tamamen sizin kontrol\u00fcn\u00fcze vermesidir.<\/dd>\n<dt><strong>5. <code>through_fields<\/code> ne i\u015fe yarar?<\/strong><\/dt>\n<dd><mark><code>through_fields<\/code><\/mark> parametresi, <mark><code>ManyToManyField<\/code><\/mark> tan\u0131mlarken kullan\u0131l\u0131r ve arac\u0131 modelinizdeki hangi <mark><code>ForeignKey<\/code><\/mark> alanlar\u0131n\u0131n ili\u015fkiyi temsil etti\u011fini a\u00e7\u0131k\u00e7a belirtmenizi sa\u011flar. Bu genellikle, arac\u0131 modelinizde birden fazla <mark><code>ForeignKey<\/code><\/mark> alan\u0131 oldu\u011funda veya ilgili modellerle ayn\u0131 tipte birden fazla <mark><code>ForeignKey<\/code><\/mark> (self-referential relations gibi) oldu\u011funda kar\u0131\u015f\u0131kl\u0131\u011f\u0131 \u00f6nlemek i\u00e7in kullan\u0131l\u0131r. <mark><code>through_fields=('from_field', 'to_field')<\/code><\/mark> \u015feklinde kullan\u0131l\u0131r ve ilk eleman <mark><code>ManyToManyField<\/code><\/mark>'nin tan\u0131mland\u0131\u011f\u0131 modelden arac\u0131 modele giden <mark><code>ForeignKey<\/code><\/mark>'i, ikinci eleman ise di\u011fer modelden arac\u0131 modele giden <mark><code>ForeignKey<\/code><\/mark>'i belirtir. \u00c7o\u011fu durumda, e\u011fer arac\u0131 modelde sadece iki <mark><code>ForeignKey<\/code><\/mark> varsa ve isimleri a\u00e7\u0131k\u00e7a ili\u015fkili modelleri g\u00f6steriyorsa, bu parametreye gerek kalmaz.<\/dd>\n<\/dl>\n","protected":false},"excerpt":{"rendered":"Django&#8217;da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak&hellip;","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-34409","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-genel","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc<\/title>\n<meta name=\"description\" content=\"Django&#039;da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django&#039;da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc\" \/>\n<meta property=\"og:description\" content=\"Django&#039;da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django&#039;da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-16T06:31:05+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc\",\"datePublished\":\"2025-11-16T06:31:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\"},\"wordCount\":2817,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\",\"name\":\"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-16T06:31:05+00:00\",\"description\":\"Django'da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django'da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc","description":"Django'da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django'da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/","og_locale":"tr_TR","og_type":"article","og_title":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc","og_description":"Django'da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django'da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.","og_url":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-16T06:31:05+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"22 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc","datePublished":"2025-11-16T06:31:05+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/"},"wordCount":2817,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/","url":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/","name":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-16T06:31:05+00:00","description":"Django'da veritaban\u0131 ili\u015fkileri kurarken s\u0131k\u00e7a kar\u015f\u0131la\u015f\u0131lan bir senaryo, iki model aras\u0131nda \u00e7oktan \u00e7o\u011fa (Many-to-Many) bir ba\u011f kurmakt\u0131r. Ancak bazen bu ili\u015fkinin kendisine ait ek bilgiler depolamak isteriz. \u0130\u015fte tam da bu noktada, arac\u0131 modeller (intermediate models) veya di\u011fer ad\u0131yla through modelleri devreye girer. Bu makale, Django'da \u00e7oktan \u00e7o\u011fa ili\u015fkilerde arac\u0131 modellerin ne i\u015fe yarad\u0131\u011f\u0131n\u0131, ne zaman kullan\u0131lmas\u0131 gerekti\u011fini ve nas\u0131l etkin bir \u015fekilde uygulanaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m a\u00e7\u0131klayacakt\u0131r.","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/django-many-to-many-iliskilerde-araci-modellerin-gucu\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Django Many-to-Many \u0130li\u015fkilerde Arac\u0131 Modellerin G\u00fcc\u00fc"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34409","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34409"}],"version-history":[{"count":0,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34409\/revisions"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34409"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34409"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}