Django-Sınıf tabanlı genel görünümlerde işleri kolaylaştıran Built-in leri tanıyalım( Built-in class-based generic views)

Django’nun generic views sayesinde views oluşturulurken  bulunan bazı ortak deyimleri ve kalıpları alırlar ve bunları soyutlarlar, böylece çok fazla kod yazmak zorunda kalmadan verilerin ortak görünümlerini(views) hızlıca yazabilirsiniz.

Nesnelerin(objects) bir listesini görüntülemek ve herhangi bir nesnenin listesini görüntüleyen bir kod yazmak gibi belirli ortak görevleri tanıyabiliriz. Daha sonra söz konusu model, URLconf'a ekstra bir argüman olarak iletilebilir.

Tek bir nesne için liste ve ayrıntı sayfalarını görüntüleyin. Konferansları yönetmek için bir uygulama oluşturuyor olsaydık, bir TalkListView ve bir RegisteredUserListView liste görünümlerinin örnekleri olabilirdi. Tek bir konuşma sayfası yani detay, "detay" görünümü dediğimiz şeyin bir örneğidir.

ÖZETLE:

Generic views(görünümler), geliştiricilerin karşılaştığı en yaygın görevleri gerçekleştirmek için hazır arayüzler sağlar.

Genel Görünümleri Genişletmek-Geliştirmek (EXTENDING GENERIC VIEWS)



Genel görünümler kullanmanın geliştirmeyi önemli ölçüde hızlandırabileceğine şüphe yok.  Ancak çoğu projede, genel görüşlerin artık yeterli olmadığı bir an gelir. Aslında, yeni Django geliştiricileri tarafından sorulan en yaygın soru, genel görünümlerin daha geniş bir dizi durumu nasıl ele alacağıdır.

Bu, 1.3 sürümü için genel görünümlerin yeniden tasarlanmasının nedenlerinden biridir - daha önce, şaşırtıcı bir seçenek dizisine sahip view functions(görüntüleme işlevleriydi); şimdi, URLconf'ta büyük miktarda yapılandırma aktarmak yerine, generic views (genel görünümleri) genişletmenin önerilen yolu, onları alt sınıflara ayırmak ve özniteliklerini veya yöntemlerini geçersiz kılmaktır.

Bazı üçüncü taraf uygulamalardan genel görünüm(generic view) örneği mevcuttur faydalanabilir veya kendi görünümünüzü yazabilirsiniz.

Nesnelerin genel görünümü(Generic views of objects)

TemplateView kesinlikle kullanışlıdır, ancak Django’nun genel görünümleri(generic views) veritabanı içeriğinizin görünümlerini sunmaya gelince gerçekten parlar.  Bu çok yaygın bir görev olduğu için, Django, nesnelerin liste halinde(ListViews) veya ayrıntılı(DetailViews) görünümlerini oluşturmaya yardımcı olacak bir avuç yerleşik genel görünümle birlikte gelir.

Nesnelerin listesini(ListViews) veya tek bir nesneyi gösteren örneklere incelemeye başlayalım.

Önce kullanacağımız modelleri(models) görelim:

# models.py
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    class Meta:
        ordering = ["-name"]

    def __str__(self):
        return self.name

class Author(models.Model):
    salutation = models.CharField(max_length=10)
    name = models.CharField(max_length=200)
    email = models.EmailField()
    headshot = models.ImageField(upload_to='author_headshots')

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField('Author')
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    publication_date = models.DateField()

Modelden sonra şimdi görünümleri(views) yazalım:

# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherList(ListView):
    model = Publisher

Görünüm kodu da yapıldı şimdi bunun urls'ye bağlanma aşamasını yapalım:

# urls.py
from django.urls import path
from books.views import PublisherList

urlpatterns = [
    path('publishers/', PublisherList.as_view()),
]
İşte bu kadar . Python kodlarını yazdık. Sırada template oluşturmak var. ;)

Görünüme bir şablon_adı(template_name) özniteliği(attribute) ekleyerek hangi şablonun kullanılacağını görünüme açıkça söyleyebiliriz, ancak belirlenmiş bir şablonun yokluğunda Django, nesnenin adından birini çıkaracaktır. Bu durumda, çıkarılan şablon "books/ publisher_list.html" olacaktır - "books" kısmı, modeli tanımlayan uygulamanın(the app) adından gelir, "yayıncı" biti ise modelin adının küçük harfli sürümüdür.

note: projenizde settings.py içinde "DIR" ALTINDA "template" klasörünü eklemeyi unutmayın.


Bu şablon object_list nesnesini publisher_list.html dosyasında görüntülemek için aşağıdaki kodu kullandık. Listenin içeriğini publisher.name göre  for döngüsü ile ekrana alındığını görüyoruz. 

{% extends "base.html" %}

{% block content %}
    <h2>Publishers</h2>
    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}

Şablondan sayfamızı da kullanmış olduk. Genel görünümlerin(generic views) harika özellikleri, genel görünümde(generic views) ayarlanan özniteliklerin (attributes) değiştirilmesinden gelir. 

Generic views kullanımını özelleştirmek ve genişletmek için kullanabileceğiniz bazı yaygın yolları ele neler olduğunu anlatmaya devam edelim.


Template contextlerin daha geliştirici dostu olması

(Making “friendly” template contexts)

Örnek yayıncı listesi şablonumuzun tüm yayıncıları object_list adlı bir değişkende sakladığını fark etmiş olabilirsiniz. Bu gayet iyi çalışsa da, şablon yazarları için o kadar "dostça" değil: burada yayıncılarla uğraştıklarını "bilmeleri" gerekiyor.


Bir model nesneyle(model objects) uğraşıyorsanız, bu sizin için zaten yapılmıştır. Bir nesne veya sorgu kümesiyle (obect or dataset) uğraşırken, Django, model sınıfının adının küçük harfli sürümünü kullanarak bağlamı (context) doldurabilir. Bu, varsayılan object_list girişine ek olarak sağlanır, ancak tamamen aynı verileri içerir, yani object_list .

Bu yine de iyi bir eşleşme değilse, bağlam(context) değişkeninin adını manuel olarak ayarlayabilirsiniz. Genel bir görünümdeki context_object_name özniteliği, kullanılacak bağlam(context) değişkenini belirtir. o zaman kodu inceleyelim :

# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherList(ListView):
    model = Publisher
    context_object_name = 'my_favorite_publishers'



Ek bilgiler ekleme(Adding extra context)

Çoğunlukla, genel görünüm(genric views) tarafından sağlananların ötesinde bazı ekstra bilgiler sunmanız gerekir. Örneğin, her bir yayıncı ayrıntı sayfasında tüm kitapların bir listesini göstermeyi düşünün. DetailView genel görünümü(generic views) yayıncıya context(bağlam) sağlar, peki bu DetailViews bu şablonu nasıl değiştirilir veya eklemeler nasıl yaparız?

Cevap, DetailView alt sınıfına girip overriding(geçersiz kılma) yapılabilir ve get_context_data metodunu kendi uygulamanızı sağlamaktır. Bununla ilgili örneği inceleyin. super() metodunu dikkatle inceleyin.

from django.views.generic import DetailView
from books.models import Book, Publisher

class PublisherDetail(DetailView):

    model = Publisher

    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet of all the books
        context['book_list'] = Book.objects.all()
        return context

Genel olarak get_context_data, tüm üst sınıfların bağlam(context) verilerini bu üst sınıftan türettiğiniz mevcut sınıflardaki contextlerle birleştirir. 
Context_data ile üst sınıftan alınan objectlerin üst sınıfta korunmaya devaö etmesi istenirse super( ) metodunu mutlaka kullanmak gerekir.

super() metodu ne yapar: Miras alarak oluşturduğumuz yani üst sınıftan oluşturduğumuz kendi sınıfımızın nitelik ve metotları üzerinde değişiklik yaparken, üst sınıfın mevcut özellikleri de muhafaza edebilmemizi sağlar.

Nesnelerin alt kümelerinin Görünümü (Viewing subsets of objects)

django da model argümanının kullanımına yakından bakalım. Hatırlayacak olursak model argümanının veritabanı(database) argumanını belirtir. Bu database leri views larda gösteririz. Bu viewslarda bir nesne veya daha fazla nesnle isteğe bağlı gösterilebilir. Database e sadece views larda değil sorgu kümesi (queryset) argümanını kullanarak nesnelerin listesini de belirtebilirsiniz. ilgil kodu inceleyelim.

from django.views.generic import DetailView
from books.models import Publisher

class PublisherDetail(DetailView):

    context_object_name = 'publisher'
    queryset = Publisher.objects.all()

Kodda geçen model = Publisher belirtilmesi, queryset = Publisher.objects.all(). demenin kısaltmasıdır. Ancak, sorgu kümesini kullanarak filtrelenmiş bir nesne listesi tanımlayabilir, görünümde görünecek nesneler hakkında daha spesifik olabilirsiniz. (Bunun için QuerySet nesneleri hakkında daha fazla bilgi için sorgular yapma konusuna bakabilirsiniz ).

Yayın tarihine göre kitap listesini almak istersek kodlar şöyle olur:

from django.views.generic import ListView
from books.models import Book

class BookList(ListView):
    queryset = Book.objects.order_by('-publication_date')
    context_object_name = 'book_list'

Belirli bir yayıncıya ait kitapların bir listesini almak için yine aynı tekniği kullanabilirsiniz:

from django.views.generic import ListView
from books.models import Book

class AcmeBookList(ListView):

    context_object_name = 'book_list'
    queryset = Book.objects.filter(publisher__name='ACME Publishing')
    template_name = 'books/acme_list.html'
Yukarıdaki örnek bir filtrelenmiş bir sorgu kümesi örneğidir. Böyle kullanımda özel bir şablon adı da kullandığımıza dikkat edin. Varsa diğer şablonlarla karışması önlenmelidir.

Dinamik Filtreleme (Dynamic Filtering)

Diğer bir yaygın ihtiyaç, bir liste sayfasında verilen nesneleri URL'deki bir anahtarla filtrelemektir. Daha önce, yayıncının adını URLconf'ta sabit bir şekilde kodlamıştık, ancak ya rasgele bir yayıncı tarafından tüm kitapları gösteren bir görünüm yazmak istersek?

Elbette, ListView geçersiz kılabileceğimiz bir get_queryset () yöntemine sahiptir. Varsayılan olarak, sorgu kümesi özniteliğinin değerini döndürür, ancak onu daha fazla mantık eklemek için kullanabiliriz.

Bu işi yapmanın en önemli kısmı, sınıfa dayalı görüşler çağrıldığında; URLconf'a göre yakalanan isme dayalı (self.kwargs) argümanların yanı sıra istek (self.request) bu konumsal (self.args) içerir ve çeşitli faydalı şeyleri kendinde saklar.

Yorum Gönder

1 Yorumlar

  1. karar ve döngü yapısı ile nasıl problem oluşturabiliriz
    1 problemi tanımlayınız
    2 problemin çözümüne ait algoritma basamaklarını yazınız
    3 problemin çözümüne ait akış şeması çiziniz
    size mail atsam acaba bana birer tane örnek yazabilir misiniz

    YanıtlaSil