Django ManytoMany sorgu yapma


#1

Arkadaşlar iyi akşamlar, ben django ile geliştirdiğim uygulamada ManytoMany ilişkiye sahip modellerim üzerinde bir sorgu gerçekleştirmek istiyorum ancak pek başarılı olduğum söylenemez. Aşağıdaki gibi modellerim var,

class Raf(models.Model):
    raf_adi = models.CharField(max_length = 50)

class Tur(models.Model):
    tur_adi = models.CharField(max_length = 50)

class Kitap(models.Model):
#konu dışı kodlar çıkartılmıştır.
    kitap_adi = models.CharField(max_length = 50)
    kitap_turu = models.ForeignKey(Tur, on_delete=models.CASCADE)
    yazar = models.ManyToManyField(Yazar)
    raf = models.ForeignKey(Raf, on_delete = models.CASCADE, blank = True, null = True)

bu modeller veritabanında şöyle alanlar oluşturuyor,

kitap
yazar
raf
kitap_yazar

benim özetle yapmak istediğim şey bir rafta bulunan kitapları yazar isimleriyle birlikte veritabanından çekmek. Bunun için denediğim bir kaç kodu paylaşayım,

def raf_detay(request, raf_id):
   #Bu iki kod ile bir rafın bilgilerini ve raf üzerindeki kitap bilgilerini alabiliyorum.
    raf = Raf.objects.filter(id = raf_id)
    kitaplar = Kitap.objects.filter(raf_id = raf_id)
   #ve bu kodlar ile de ilgili rafta bulunan kitaplara ait yazarları
    kitap_yazar = []
    for kitap in kitaplar:
        kitap_yazar.append(Yazar.objects.filter(kitap__id = kitap.id))

ve bunları template içinde bir card ile bir araya getirmeye çalışıyorum, ancak hangi yazarın hangi kitaba ait olduğunu eşleştiremiyorum. Bu noktada 2 sorum olacak,

  1. Bu izlediğim yol böyle bir senaryo için doğru mudur? Değilse nasıl olması gerektiği konusunda bir örnek paylaşırsanız çok memnun olurum.
  2. Eğer işe yarar bir yöntemse bunları template de nasıl ilgili kitaplarla eşleştirebilirim?

#2

django ORM ni pek bilmiyorum
ama shell de veya command promt da
qs = Model.objects.filter(name=‘test’)
print(qs.query) ile sql e giden sorguya bakabilirsiniz.
günün sonunda ORM de sql syntax ini kullanıyor.
join ler vesaire
size dönemesi gereken sonuç
select * from raf with(nolock) left outer join on kitap.raf_id = raf.id
where raf.id = 1 atıyorum bunları
django da sql syntax i kendiniz kullanacaksanız sql injection a dikkat edin.
orm bu anlamda koruyucu ama ben pek bilmiyorum karışık geliyor bana


#3

İlgilendiğiniz için teşekkür ederim.

Bu aklıma gelmemişti. Ben çözemedim buradan da bir cevap çıkmayınca foreginkey ile yapmıştım ama bugün sorguyu inceleyeceğim.

Uygulamada kitap tür eşleştirmesi yaparken de ManytoMany olması gerektiğini farkettim ve artık bu sorunu aşmak için sınırlarımı zorladım. Sonuç olarak ortaya şöyle birşey çıktı,

def get_tur(kitap_id):
#bu with olayınıda öğrenebilmiş değilim nerde nasıl kullanılıyor. Bu konuda biri 
#yeşillendirirse memnun olurum.
	with connection.cursor() as cursor:
		cursor.execute(
			f'''
			SELECT tur_id, tur_adi
			FROM Tur_tur
			INNER JOIN Kitap_kitap_tur
			ON Tur_tur.id = Kitap_kitap_tur.tur_id
			WHERE Kitap_kitap_tur.kitap_id = {kitap_id}
			'''
			)
		tur = cursor.fetchall()
	return tur

def kitap_detay(request, kitap_id):
	kitap = Kitap.objects.filter(id = kitap_id)
	for i in kitap:
		global raf
		global tur
		raf = Raf.objects.filter(id = i.raf_id)
		tur = get_tur(i.id)

burdaki sql komutları kısmınada çok hakim değilim becerebilirsem yazar kısmında da bu uyarlamayı yapmaya çalışacam ama önce sizin dediğiniz yöntemle bir sql kodlarını inceleyip mümkünse ORM ile devam etmek istiyorum.