Django'da Sınıf ve Fonksiyon Temeli Görünümler (Class-Based Views ve Function-Based Views)

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.

Django'da Sınıf ve Fonksiyon Temeli Görünümler

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

Paylaş

Yeni Blog Yazılarımdan Haberdar Olun

Yeni yazılarımdan anında haberdar olmak için email listeme abone olun. Size spam göndermeyeceğime söz veriyorum!