Django Framework'ün geliştiricilere sunduğu en önemli felsefi unsur "kolaylık ve sadelik" olsa gerek. Halihazırda dev şirketlerin güvenerek kullandığı, her modülü ve özelliğiyle en karmaşık web sitelerini dahi kolayca oluşturmamızı sağlayan bu altyapı, arayüz etkileşimi için sunduğu Görünümler (views) katmanında da bu felsefesini ortaya koyuyor. Bu konuda daha önce sizlerle paylaştığım Django Framework Neden Tercih Edilmeli? konulu yazım ilginizi çekebilir.
Django bize görünümler (views) için iki farklı yol sunuyor. Birincisi Fonksiyon Temelli Görünümler (Function-Based Views), ikincisi Sınıf Temelli Görünümler (Class-Based Views). Her iki seçenek de aynı yola çıkan fakat geliştiricilerin o yolda kendilerini daha konforlu hissedebilecekleri alternatifler sunuyor.
Django'nun DRY (Don't Repeat Yourself) Türkçe olarak "Kendini Tekrar Etme" ile kolaylık ve sadelik felsefesi ışığında öne çıkan Sınıf Temelli Görünümler, birçok işi kolayca yapabilmemizi sağlıyor.
Sınıf Temelli Görünümler (Class-Based Views):
Sınıf temelli görünümlerin amacı kısaca işimizi kolaylaştırmaktır. Bize bunun için CRUD (Create-Read-Update-Delete) işlemlerini kolayca gerçekleştirebileceğimiz birkaç araç sunar.
1. CreateView
2. DeleteView
3. UpdateView
4. ListView
5. FormView
6. DetailView
7. TemplateView
8. RedirectView
9. View
Temel olarak projelerinizde sıklıkla kullanacağınız görünümler bunlar olsada, LoginView, PasswordChangeView, ArchiveIndexView ve bunlar gibi birkaç spesifik views sınıfı daha bulunmaktadır. Bu ayrıntılara Django belgelerinden ulaşabilirsiniz. Ben burada sizler için temel noktalara değineceğim.
Örnekler üzerinden gidersek çok daha anlaşılır olacağını düşünüyorum. Örneğin gelin bir blog için yazıların listelendiği ListView görünümler sınıfı nasıl olur inceleyelim.
class BlogList(ListView):
template_name = 'blog_list.html' # hangi template şablonda gözükeceğini belirliyoruz
model = Blog # içeriğin alınacağı model ile bağlantı kuruyoruz
ListView ile bunu ne kadar basitçe yaptığımıza bakın. Class-Based Views'in sağladığı kolaylık, bizim için her şeyi organize etmesinden kaynaklanıyor. Eğer istersek sayfalama sınırını paginate_by değişkeniyle tanımlayabilirdik veya sıralamayı ordering değişkeni ile tanımlayabilir ve get_context_data metodu ile şablonumuza başka modellerden context gönderebilir yada context_object_name ile şablonumuz için özel context adı tanımlayabilirdik. Bu şöyle gözükürdü:
class BlogList(ListView):
template_name = 'blog_list.html' # hangi template şablonda gözükeceğini belirliyoruz
model = Blog # içeriğin alınacağı model ile bağlantı kuruyoruz
context_object_name = 'blog_list' # şablon için özel context adı tanımlıyoruz
ordering = ['yayinlanma_tarihi'] # queryset listesini sıralıyoruz
paginate_by = 10 # her sayfada 10 yazı gözükecek şekilde sınırlıyoruz
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) # şablon için verileri oluşturuyoruz
context['hakkimda_query'] = get_object_or_404(Hakkimda) # şablona ek içerik gönderiyoruz
return context
Sınıf Tabanlı Görünümlerin bunlar gibi ek metodları bulunuyor. Bizim örnekten anlamamız gereken şey, organizasyonun nasıl da otomatik şekilde yapılmış olduğudur.
Ek bilgi:
• template_name varsayılan değeri: <app_label>/<model_name>_list.html
• context_object_name varsayılan değeri: object_list
• queryset varsayılan değeri: Model.objects.all()
Bir başka örnek verecek olursak (bir formumuzun olduğunu varsayalım):
1. Yol (Class-based Views):
class OrnekCreateView(View):
template_name = 'form.html' # hangi template şablonda gözükeceğini belirliyoruz
form_class = OrnekForm # hangi formu kullanacağını belirliyoruz
def get(self, request, *args, **kwargs):
form = self.form_class # formdan bir örnek oluşturuyoruz
return render(request, template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid(): # eğer form alanları sorunsuz dönüyorsa
form.save() # kaydediyoruz
return HttpResonseRedirect(reverse('list-view'))
else:
return render(request, self.template_name, {'form': form})
2. Yol (Generic Class-based Views):
class OrnekCreateView(CreateView):
model = MyModel
form_class = OrnekForm
CreateView ile form sayfamızın ne kadar basitçe oluşturulduğuna bakın.
Fonksiyon Temelli Görünümler (Function-Based Views):
Karşılaştırılması kolay olması açısından aynı işlemleri fonksiyon tabanlı görünümlerle deneyelim.
def bloglist(request):
yazilar = Blog.objects.all() # hangi modelden queryset oluşturacağımızı belirliyoruz
return render(request, 'blog_list.html', {'yazilar': yazilar}) # şablona context dönderiyoruz
Yine aynı şekilde ek özellikleri ekleyerek örnek verelim:
def bloglist(request):
blog_list = Blog.objects.order_by('yayinlanma_tarihi')
hakkimda_query = get_object_or_404(Hakkimda)
page = request.GET.get('page', 1)
paginator = Paginator(blog_list, 10)
try:
yazilar = paginator.page(page)
except PageNotAnInteger:
yazilar = paginator.page(1)
except EmptyPage:
yazilar = paginator.page(paginator.num_pages)
context = {
"yazilar": yazilar,
"hakkimda_query": hakkimda_query
}
return render(request, 'blog_list.html', context)
Son örneğimiz ise şöyle görünecektir:
def ornek_create_view(request, pk):
template_name = 'form.html'
form_class = OrnekForm
form = form_class
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('list-view'))
return render(request, template_name, {'form': form})
Aradaki farkı görebiliyor musunuz? Fonksiyon temelli görünümler okunuş açısından bazı geliştiricilere daha okunaklı gelsede, genel itibariyle sınıf bazlı görünümler daha kolay okunurlar. Çünkü bir çok işlevi otomatik olarak arka planda hallederler. Ancak bu demek değildir ki Class Views daha iyidir.
Sınıf Temelli Görünümler mi Fonksiyon Temelli Görünümler mi Daha İyi?
Bu soruya cevap vermeden önce şunu netleştirmenin lüzumunu hissediyorum. Sınıf Temelli Görünümler, Fonksiyon Temelli Görünümlerin yerine geliştirilmemiştir. Her ikisinin de amacı farklıdır. Class Views "bazı işleri" kolayca halletmemiz için bize sunulmaktadır. Ancak her şeyin üstesinden kolayca gelemezler. Bu sebeple views.py dosyalarınızı düzenlerken illa Class Views ile görünümler hazırlamaya kendinizi zorlamayın. Bu yanlış olacaktır.
Django biz geliştiriciler için güçlü bir altyapıyla basit ve sadeliği sunmaktadır. Bunu en iyi şekilde anlayıp kullanmak ve her zaman Django gibi düşünmek en doğru seçim olacaktır.
Basit düşün - sade ol - kendini tekrar etme