Featured image of post Django'da Her View'a Aynı Veriyi Göndermekten Kurtulun: Context Processor

Django'da Her View'a Aynı Veriyi Göndermekten Kurtulun: Context Processor

Django Context Processor Nedir ve Nasıl Kullanılır

Django’da proje geliştirirken bir noktada hepimiz aynı duvara toslarız: Sitenin her sayfasında (örneğin navbar’da, sidebar’da veya footer’da) göstermemiz gereken bazı dinamik veriler vardır. Kategori listeleri, sepetteki ürün sayısı, okunmamış bildirimler veya genel site ayarları gibi…


İlk başlarda bu verileri her View fonksiyonunun içinde tek tek çağırıp template’e göndermek göze batmaz. Ancak proje büyüdükçe context sözlükleri şişmeye başlar ve kod tekrarı (DRY - Don’t Repeat Yourself ihlali) can sıkıcı bir hal alır.

İşte Django’nun bu duruma getirdiği şık çözümün adı Context Processor.

Context Processor Aslında Nedir?

Çok temel düzeyde düşünürsek; Context Processor sadece bir HTTP request nesnesi alan ve döndürdüğü sözlüğü (dictionary) tüm şablonların (templates) kullanımına açan basit bir Python fonksiyonudur.

Zaten farkında olmadan bunları sürekli kullanıyoruz. Şablonlarda hiçbir view’dan veri göndermediğiniz halde {{ user.is_authenticated }} veya {{ request.path }} yazabildiğinizi düşünün. Bunlar Django’nun varsayılan context processor’larının arka planda çalışmasının bir sonucudur.

Kendi Context Processor’ımızı Yazalım

Diyelim ki blogumuzun her sayfasında göstermek istediğimiz site ayarları ve o anki yıl bilgisi var. Bunu adım adım projemize nasıl entegre edeceğimize bakalım.

1. Fonksiyonu Oluşturmak

Öncelikle app dizininizin içinde (ben bu tarz genel yapıları genellikle core veya common gibi bir app içinde tutarım) context_processors.py adında yeni bir dosya oluşturun:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# core/context_processors.py

def global_settings(request):
    # Veritabanı sorguları veya mantıksal işlemler buraya gelebilir.
    # Şimdilik statik verilerle ilerleyelim.
    return {
        'SITE_NAME': 'Benim Teknoloji Blogum',
        'SUPPORT_EMAIL': '[email protected]',
        'CURRENT_YEAR': 2026
    }

2. Django’ya “Bunu Kullan” Demek

Yazdığımız fonksiyonun projenin her yerinde çalışması için onu settings.py dosyasındaki TEMPLATES ayarının içine kaydetmemiz gerekiyor.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                # Yazdığımız processor'ın yolunu buraya ekliyoruz
                'core.context_processors.global_settings', 
            ],
        },
    },
]

3. Template İçinde Doğrudan Kullanım

Artık bu değişkenleri view üzerinden yollamanıza gerek yok. Projedeki herhangi bir HTML dosyasında (özellikle base.html gibi ana iskelet dosyalarında) direkt çağırabilirsiniz:

1
2
3
4
5
6
7
8
<header>
    <h1>{{ SITE_NAME }}</h1>
</header>

<footer>
    <p>&copy; {{ CURRENT_YEAR }} Tüm hakları saklıdır.</p>
    <p>İletişim: {{ SUPPORT_EMAIL }}</p>
</footer>

Dikkat: Performans Tuzağına Düşmeyin

Context Processor’lar hayat kurtarır ama aynı zamanda dikkatsiz kullanıldığında projenizin performansını bir anda yerle bir edebilir.

Neden mi? Çünkü settings.py dosyasına eklediğiniz bir context processor, sitenizde render edilen istisnasız her bir sayfa için yeniden çalıştırılır. Eğer bu fonksiyonun içine gidip Article.objects.all() gibi ağır bir veritabanı sorgusu atarsanız, sitenize giren her kullanıcı, her sayfa değişiminde o devasa sorguyu veritabanında tekrar tetikler.

Eğer veritabanından veri çeken bir context processor yazmanız gerekiyorsa (ki dinamik menüler için çoğu zaman gerekecektir), o sorguyu mutlaka Django’nun Cache (Önbellekleme) mekanizması ile sarmalamanız şarttır. Aksi takdirde veritabanınız gereksiz yük altında ezilir.

Performans Dostu Çözüm: Context Processor ve Cache (Önbellekleme)

Eğer Context Processor içinde veritabanı sorgusu yapmanız gerekiyorsa (örneğin tüm sayfalarda dinamik bir kategori menüsü göstermek için), bunu çıplak bir ORM sorgusuyla yapmak sitenizi yavaşlatır. Her sayfa yenilendiğinde aynı kategoriler için veritabanına tekrar tekrar gidilir.

Çözüm, sonucu belirli bir süreliğine bellekte (RAM) tutmaktır. Django’nun yerleşik cache modülünü kullanarak bunu çok zarif bir şekilde çözebiliriz.

Önbellekli Context Processor Örneği

Diyelim ki blogumuzun sidebar‘ında göstermek için aktif kategorileri çeken bir fonksiyon yazıyoruz. Kodumuz şu şekilde olmalı:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# core/context_processors.py

from django.core.cache import cache
from blog.models import Category # Kendi modelinizi import edin

def category_menu(request):
    # 1. Önce veriyi önbellekte (cache) arıyoruz
    categories = cache.get('navbar_categories')
    
    # 2. Eğer veri önbellekte yoksa (süresi dolmuşsa veya ilk kez çalışıyorsa)
    if categories is None:
        # Veritabanına sadece bu durumda gidiyoruz
        categories = Category.objects.filter(is_active=True)
        
        # 3. Sonucu 1 saatliğine (3600 saniye) önbelleğe kaydediyoruz
        cache.set('navbar_categories', categories, timeout=3600)
        
    return {
        'MENU_CATEGORIES': categories
    }

Bu Kod Bize Ne Kazandırdı?

  1. Veritabanı Rahatladı: Kullanıcı sitenizde 50 farklı sayfayı gezse bile, veritabanına sadece 1 kez sorgu atılır. Kalan 49 sayfa gösteriminde veriler ışık hızıyla RAM’den (önbellekten) gelir.
  2. Ölçeklenebilirlik: Sitenizin trafiği aniden artsa bile menü sorguları veritabanını kilitlemez.

Küçük Bir İpucu: Django varsayılan olarak Local Memory Cache kullanır ve küçük projeler için yeterlidir. Ancak projeyi gerçek bir sunucu ortamına taşıdığınızda, önbellek verilerini yönetmek için Redis veya Memcached kullanmak endüstri standardıdır. Özellikle geliştirme ve canlı ortamlarınızı izole bir şekilde yönetiyorsanız, mimarinize küçük bir Redis konteyneri eklemek bu sistemi kusursuz hale getirecektir.