Django 5.2 Middleware ve Signal Mekanizmalari: Teknik Mulakat Rehberi
Django 5.2'de custom middleware yazimi, signal handling, post_save, pre_save, async middleware ve domain olaylari. Teknik mulakat sorularina yonelik kapsamli rehber ve Python kod ornekleri.

Django'nun middleware ve signal mekanizmalari, framework'un istek isleme hattini ve bilesenler arasi iletisimi yoneten iki temel yapisal unsurdur. Middleware, her HTTP isteginin ve yanitinin gecirdigi katmanli bir boru hatti sunarken, signal'lar modeller ve uygulamalar arasinda gevsek bagli (loosely coupled) bir olay mekanizmasi saglar. Django 5.2 LTS surumunde async middleware desteginin olgunlasmasi ve signal altyapisindaki iyilestirmeler, bu iki mekanizmayi teknik mulakatlarda siklikla sorgulanan konular arasina tasimistir. Bu rehber, her iki mekanizmayi uretim ortamina uygun kod ornekleriyle ele almakta ve mulakatlarda karsilasilan kritik noktalari aydinlatmaktadir.
- Middleware: Istek/yanit dongusu uzerinde calisan katmanli boru hatti. Her istek tum middleware zincirinden gecer.
- Signal: Belirli olaylarda (model kaydi, istek baslangici vb.) tetiklenen publish-subscribe mekanizmasi.
process_exception: Yalnizca view bir istisna firlattiginda cagrilir; middleware'in__call__icindeki hatalar bu hook'u tetiklemez.post_savevspre_save:post_saveveritabani yaziminden sonra,pre_saveyazimdan once calisir.post_saveicindeinstance.save()cagirmak sonsuz donguye neden olabilir.- Async middleware: Django 5.2'de
async_capable = Truevesync_capable = Falseile tanimlanir;get_responseawaitile cagirilir.
Django Middleware Nasil Calisir
Django'da middleware, istek-yanit dongusunun her asamasinda devreye giren bir katmandir. Her middleware sinifi, __init__ metodunda bir defaya mahsus yapilandirma gerceklestirir ve __call__ metodunda her istegi isler. get_response parametresi, zincirdeki bir sonraki middleware'i veya nihayetinde view fonksiyonunu temsil eder. Bu tasarim, sorumluluk zinciri (chain of responsibility) deseninin Django'daki uygulamasidir.
# middleware.py - Basic middleware structure
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration happens here at server start
def __call__(self, request):
# Code executed BEFORE the view (and later middleware)
response = self.get_response(request)
# Code executed AFTER the view (on the way back)
return response__init__ metodu sunucu baslatildiginda yalnizca bir kez calisir ve burada veritabani baglantilari, onbellek istemcileri veya yapilandirma degerleri hazirlanabilir. __call__ metodu ise her istekte cagrilir. self.get_response(request) satirinin oncesinde yazilan kod istek asamasinda (view'a giden yolda), sonrasinda yazilan kod ise yanit asamasinda (view'dan donen yolda) calisir. Bu iki fazli yapi, middleware'in hem istegi on-islemeden gecirmesine hem de yaniti son-islemeden gecirmesine olanak tanir.
Istek Loglama Middleware'i Olusturma
Uretim ortamlarinda her istegin sure, durum kodu ve IP adresi ile loglanmasi, performans izleme ve hata ayiklama icin kritik bir gereksinimdir. Asagidaki middleware, her istegi yapilandirilmis log formatiyla kaydeder ve process_exception hook'u araciligiyla view kaynakli istisnalari yakalar.
# apps/core/middleware.py
import logging
import time
logger = logging.getLogger('django.request')
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.monotonic()
# Attach metadata before view processing
request.start_time = start_time
response = self.get_response(request)
duration = time.monotonic() - start_time
logger.info(
'method=%s path=%s status=%d duration=%.3fs ip=%s',
request.method,
request.get_full_path(),
response.status_code,
duration,
request.META.get('REMOTE_ADDR'),
)
return response
def process_exception(self, request, exception):
# Called only when the view raises an exception
duration = time.monotonic() - getattr(request, 'start_time', 0)
logger.error(
'method=%s path=%s exception=%s duration=%.3fs',
request.method,
request.get_full_path(),
str(exception),
duration,
)
return None # Let Django's default exception handling continuetime.monotonic() kullanimi, sistem saatindeki degisikliklerden etkilenmeyen hassas sure olcumu saglar. process_exception metodu, yalnizca view bir istisna firlattiginda devreye girer; None dondurerek Django'nun varsayilan istisna isleme mekanizmasinin calismaya devam etmesini saglar. request nesnesine start_time gibi ek niteliklerin eklenmesi, farkli middleware'ler arasinda veri paylasiminin yaygin bir yontemidir.
Middleware Siralamasi ve MIDDLEWARE Ayari
Middleware siralamasi, Django uygulamalarinda kritik bir yapilandirma kararidir. MIDDLEWARE listesindeki siralama, istek isleme sirasini dogrudan belirler: istekler listede yukaridan asagiya, yanitlar ise asagidan yukariya dogru ilerler. Guvenlik middleware'i en ustte yer almali, oturum ve kimlik dogrulama middleware'leri CSRF korumasindan sonra gelmelidir.
# settings.py - Middleware ordering matters
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Custom middleware placed after Django's core stack
'apps.core.middleware.RequestLoggingMiddleware',
]Ozel middleware genellikle Django'nun cekirdek yigininin altina yerlestirilir. Bu konumlama, ozel middleware calistiginda oturum, kimlik dogrulama ve CSRF korumalarinin halihazirda uygulanmis olmasini garanti eder. Eger ozel middleware request.user erisimi gerektiriyorsa, AuthenticationMiddleware altinda konumlandirilmasi zorunludur; aksi halde AnonymousUser nesnesiyle karsilasilir.
Mulakatlarda siklikla sorulan bir soru, middleware siralamasi degistirildiginde ne olacagidir. Ornegin, SecurityMiddleware listenin sonuna alinirsa, HSTS baslik ekleme ve SSL yonlendirmesi diger tum middleware'lerden sonra gerceklesir; bu da guvenlik aciklarina yol acabilir.
Django 5.2'de Async Middleware
Django 5.2, ASGI sunucularinda (Daphne, Uvicorn) calisirken tamamen asenkron middleware yazimini desteklemektedir. async_capable = True ve sync_capable = False sinif degiskenleri, Django'ya bu middleware'in yalnizca asenkron baglamda calistigini bildirir. Bu sayede get_response bir awaitable olarak kullanilabilir ve I/O islemleri bloklamadan gerceklestirilir.
# apps/core/middleware.py
import asyncio
import time
class AsyncTimingMiddleware:
# Mark this middleware as async-capable
async_capable = True
sync_capable = False
def __init__(self, get_response):
self.get_response = get_response
async def __call__(self, request):
start = time.monotonic()
# get_response is awaitable in async context
response = await self.get_response(request)
duration = time.monotonic() - start
response['X-Request-Duration'] = f'{duration:.4f}s'
return responseAsync middleware, veritabani sorgulari, harici API cagrilari veya dosya islemleri gibi I/O yogun operasyonlarda onemli performans kazanimlari saglar. sync_capable = False ayari, bu middleware'in senkron WSGI sunucularinda kullanilamayacagini belirtir. Hem senkron hem de asenkron ortamlarda calisabilecek bir middleware icin her iki degiskenin de True olarak ayarlanmasi ve __call__ ile async __call__ metotlarinin ayri ayri tanimlanmasi gerekir.
Multakatlarda async middleware ile ilgili kritik bir soru, senkron ve asenkron middleware'lerin ayni zincirde karistirildigi durumlardadir. Django bu senaryoda otomatik adaptorler kullanir ancak her gecis bir performans maliyeti olusturur. Bu nedenle middleware zincirinin tamamen senkron veya tamamen asenkron olarak tutulmasi onerilen yaklasimdir.
Django mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Django Signal'lari: Publish-Subscribe Deseni
Django signal'lari, framework icinde yerlesik bir publish-subscribe mekanizmasi sunar. Bir bilesenin (gonderen/sender) belirli bir olayi tetiklemesi ve diger bilesenlerinin (alici/receiver) bu olaya tepki vermesi prensibine dayanir. Bu mekanizma, bilesenler arasindaki dogrudan bagimliligi ortadan kaldirarak modullerin birbirinden bagimsiz olarak gelistirilmesini ve test edilmesini kolaylastirir.
Django'nun yerlesik signal'lari arasinda en sik kullanilanlar sunlardir:
pre_save: Model ornegi veritabanina yazilmadan hemen once tetiklenir. Veri dogrulama, normalizasyon ve otomatik alan doldurma icin idealdir.post_save: Model ornegi veritabanina yazildiktan hemen sonra tetiklenir. Iliskili nesne olusturma, bildirim gonderme ve onbellek gecersiz kilma icin kullanilir.pre_delete/post_delete: Silme islemi oncesinde ve sonrasinda tetiklenir.request_started/request_finished: Her HTTP isteginin baslangicinda ve sonunda tetiklenir.
Signal'lar ile middleware arasindaki temel fark, calisma katmanidir. Middleware HTTP istek/yanit dongusunde calisirken, signal'lar model katmaninda veya belirli framework olaylarinda devreye girer. Her iki mekanizma da farkli sorumluluk alanlarini hedefler ve birbirlerinin yerine gecmez.
post_save ile Otomatik Profil Olusturma
post_save signal'inin en yaygin kullanim alani, yeni bir kullanici olusturuldugunda iliskili bir profil nesnesinin otomatik olarak olusturulmasidir. created parametresi, signal'in bir INSERT (yeni kayit) mi yoksa UPDATE (guncelleme) mi sonucu tetiklendigini ayirt etmeye olanak tanir.
# apps/accounts/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from apps.accounts.models import UserProfile
User = get_user_model()
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
# 'created' is True only on INSERT, False on UPDATE
if created:
UserProfile.objects.create(
user=instance,
display_name=instance.get_full_name() or instance.username,
)@receiver dekoratoru, create_user_profile fonksiyonunu User modelinin post_save signal'ina baglar. created parametresi True oldugunda yeni bir kullanici olusturuldugu anlasilir ve yalnizca bu durumda profil nesnesi uretilir. Bu yaklasim, profil olusturma mantgini kullanici kayit isleminden ayirarak tek sorumluluk prensibine uygun bir yapi saglar.
Mulakatlarda onemli bir nokta: post_save icinde instance.save() cagirmak sonsuz bir donguye neden olur cunku save() yeniden post_save signal'ini tetikler. Bu durumdan kacinmak icin update_fields parametresi kullanilmali veya QuerySet.update() tercih edilmelidir.
pre_save ile Veri Dogrulama ve Donusum
pre_save signal'i, verinin veritabanina yazilmasindan hemen once mudahale etme olanagi sunar. Slug olusturma, tarih normalizasyonu ve hesaplanmis alan guncellemesi gibi islemler icin idealdir. Asagidaki ornekte, bir blog makalesinin slug alani bos birakildiysa basliktan otomatik olarak uretilmekte ve benzersizligi garanti edilmektedir.
# apps/blog/signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.utils.text import slugify
from apps.blog.models import Article
@receiver(pre_save, sender=Article)
def auto_generate_slug(sender, instance, **kwargs):
if not instance.slug:
base_slug = slugify(instance.title)
slug = base_slug
counter = 1
# Ensure slug uniqueness
while Article.objects.filter(slug=slug).exclude(pk=instance.pk).exists():
slug = f'{base_slug}-{counter}'
counter += 1
instance.slug = slugpre_save signal'inin post_save'den temel farki, yapilan degisikliklerin ayri bir save() cagrisi gerektirmeden veritabanina yansitilmasidir. instance.slug atamasinin ardindan Django, bu guncellenenmis degeri otomatik olarak INSERT veya UPDATE sorgusuna dahil eder. Bu ozellik, sonsuz dongu riskini ortadan kaldirir ve pre_save'i veri donusum islemleri icin post_save'den daha guvenli bir tercih haline getirir.
Benzersiz slug uretim algoritmasi, exclude(pk=instance.pk) filtresiyle mevcut kaydin kendi slug'iyla catismasini onler. Bu detay, guncelleme senaryolarinda ozellikle onemlidir.
Signal'larin AppConfig.ready() ile Kaydedilmesi
Signal receiver'larinin dogru bir sekilde kaydedilmesi, Django uygulamasinin saglikli calismasi icin kritik bir adimdir. Signal modulleri, uygulama yapilandirma sinifinin ready() metodu icinde import edilmelidir. Bu metot, Django baslangic surecinde tum uygulamalar yuklendikten sonra yalnizca bir kez calisir.
# apps/accounts/apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.accounts'
def ready(self):
# Import signals module to register receivers
import apps.accounts.signals # noqa: F401ready() metodu, signal modulu icindeki @receiver dekoratorlerinin Django'nun signal dispatcher'ina kaydedilmesini saglar. Bu import islemi baska bir yerde (ornegin models.py veya __init__.py icinde) gerceklestirilirse, dairesel import hatalari veya signal'larin birden fazla kez kaydedilmesi gibi sorunlarla karsilasilabilir. # noqa: F401 yorumu, linter'in kullanilmayan import uyarisini bastirmak icindir.
Mulakatlarda siklikla sorulan bir hata senaryosu, ready() icinde signal import'unun unutulmasidir. Bu durumda @receiver dekoratoru hicbir zaman calistirilmaz ve signal handler'lari sessizce devre disi kalir -- uygulama hata vermez ancak beklenen davranis gerceklesmez.
Ozel Domain Olaylari icin Custom Signal Tanimlama
Django'nun yerlesik signal'larinin otesinde, uygulamaya ozgu is kurallari icin ozel signal'lar tanimlanabilir. Bu yaklasim, bir siparis tamamlandiginda farkli bilesenlerin (e-posta gonderimi, stok guncelleme, analitik kaydi) birbirinden bagimsiz olarak tepki vermesine olanak tanir. Ozel signal'lar, django.dispatch.Signal sinifi araciligiyla tanimlanir.
# apps/orders/signals.py
from django.dispatch import Signal
# Define custom signals with documentation
order_completed = Signal() # Sent after payment confirmation
order_refunded = Signal() # Sent after refund processing
# apps/orders/services.py
from apps.orders.signals import order_completed
def complete_order(order):
order.status = 'completed'
order.save()
# Dispatch signal with relevant context
order_completed.send(
sender=order.__class__,
order=order,
total=order.total_amount,
)
# apps/notifications/receivers.py
from django.dispatch import receiver
from apps.orders.signals import order_completed
@receiver(order_completed)
def send_order_confirmation_email(sender, order, **kwargs):
# Email logic decoupled from order processing
from apps.notifications.services import send_email
send_email(
to=order.customer.email,
template='order_confirmation',
context={'order': order},
)Bu ornekte siparis isleme mantigi (complete_order) bildirim mantgindan (send_order_confirmation_email) tamamen ayristirilmistir. Siparis servisi yalnizca signal'i gondermekle yetinir; hangi bilesenlerin bu olaya tepki verecegini bilmesine gerek yoktur. Bu yapi, acik-kapali prensibine (Open-Closed Principle) uyumludur: yeni bir davranis eklemek icin siparis servisinin degistirilmesine gerek kalmaz, yalnizca yeni bir receiver tanimlanir.
signal.send() metodu senkron olarak calisir ve tum receiver'larin donus degerlerini bir liste halinde dondurur. Uzun suren islemler (e-posta gonderimi, harici API cagrilari) icin receiver icinde Celery gibi bir gorev kuyrugu kullanilmasi, istek yanit suresinin uzamasini onlemek acisindan onerilen yaklasimdir.
Mulakatlarda Sik Karsilasilan Tuzaklar
Django middleware ve signal mekanizmalari, teknik mulakatlarda adaylarin derinlemesine bilgisini olcmek icin kullanilan cesitli tuzak sorulari icerir. Asagidaki iki nokta, en sik karsilasilan ve en cok hata yapilan konulari ozetlemektedir.
QuerySet.update() ve QuerySet.delete() toplu islemleri, model ornegi uzerinden gecmeden dogrudan SQL sorgusu calistirir. Bu nedenle pre_save, post_save, pre_delete ve post_delete signal'lari tetiklenmez. Toplu islemlerde signal'larin calismasinin beklendigi senaryolar, mulakatlarda en sik gozden kacirilan noktalardan biridir. Cozum olarak nesneler uzerinde tek tek save() veya delete() cagirilmalidir ya da post_save yerine veritabani trigger'lari kullanilmalidir.
Django 5.2, Uzun Vadeli Destek (LTS) surumudur ve Nisan 2028'e kadar guvenlik guncellemeleri alacaktir. Uretim ortamlari icin LTS surumu tercih edilmelidir. Django 5.2 ile gelen onemli iyilestirmeler arasinda async view ve middleware desteginin olgunlasmasi, composite primary key destegi ve gelismis QuerySet yontemleri yer almaktadir. Mulakatlarda Django surum politikasi ve LTS secimi hakkinda sorular sorulabilir.
Ek olarak, su tuzaklar da mulakat baglamindan siklikla karsimiza cikmaktadir:
- Signal siralama garantisi yoktur: Ayni signal'a baglanan birden fazla receiver'in calisma sirasi tanimli degildir. Is mantigi belirli bir siralamaya bagimli olmamalidir.
- Signal'lar transaksiyonel degildir:
post_savesignal'i, veritabani transaksiyonu commit edilmeden once calisir.transaction.on_commit()kullanilmazsa, receiver icindeki islemler geri alinan (rollback edilen) veriler uzerinde gerceklesebilir. - Middleware
__init__icinde veritabani erisimi:__init__metodu sunucu baslatildiginda calisir ve bu asamada veritabani baglantisi hazir olmayabilir. Veritabani erisimi__call__icinde gerceklestirilmelidir.
Middleware ve Signal Karsilastirma Tablosu
| Ozellik | Middleware | Signal |
|---|---|---|
| Calisma katmani | HTTP istek/yanit dongusu | Model katmani ve framework olaylari |
| Tetiklenme | Her HTTP isteginde | Belirli olaylarda (save, delete, request) |
| Siralama | MIDDLEWARE listesindeki sira ile belirlenir | Tanimli bir siralama garantisi yoktur |
| Kapsam | Tum isteklere uygulanir | Belirli model veya olaya baglidir |
| Async destegi | Django 5.2'de tam destek | Sinirli (senkron dispatcher) |
| Kullanim alani | Loglama, guvenlik, CORS, hiz sinirlandirma | Profil olusturma, bildirim, onbellek gecersiz kilma |
| Test edilebilirlik | RequestFactory ile dogrudan test | signal.disconnect() ile izole test |
| Performans etkisi | Her istekte calisir | Yalnizca ilgili olay gerceklestiginde calisir |
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Sonuc
Django'nun middleware ve signal mekanizmalari, uygulamanin farkli katmanlarinda farkli sorumluluklar ustlenen tamamlayici yapilardir. Teknik mulakatlarda bu iki mekanizmanin derinlemesine anlasilmasi, aday degerlendirmesinde belirleyici bir rol oynamaktadir. Temel cikarimlar su sekilde ozetlenebilir:
- Middleware, HTTP istek/yanit dongusunun her asamasinda calisan katmanli bir boru hatti sunar.
__call__icindekiget_responsecagrisi oncesi ve sonrasi, sirasiyla istek ve yanit islemlerini temsil eder. - Middleware siralamasi kritiktir: guvenlik middleware'i en ustte, ozel middleware Django'nun cekirdek yigininin altinda konumlandirilmalidir.
- Django 5.2'de async middleware, ASGI sunucularinda bloklama olmadan I/O islemlerini gerceklestirmeye olanak tanir. Senkron ve asenkron middleware'lerin karistirilmasi performans maliyeti olusturur.
pre_savesignal'i veri donusum islemleri icin idealdir cunku degisiklikler ayri birsave()cagrisi gerektirmez.post_saveise iliskili nesne olusturma ve bildirim gonderme icin uygundur.QuerySet.update()veQuerySet.delete()toplu islemleri signal tetiklemez -- bu, mulakatlarda en sik karsilasilan tuzaklardan biridir.- Custom signal'lar, domain olaylarini bilesenlere yaymak icin acik-kapali prensibine uygun bir mekanizma sunar.
- Signal receiver'lari
AppConfig.ready()icinde import edilmelidir; aksi halde sessizce devre disi kalir. post_saveicindetransaction.on_commit()kullanilmasi, receiver'in geri alinan veriler uzerinde calismasi riskini ortadan kaldirir.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Etiketler
Paylaş
İlgili makaleler

Django Mülakat Soruları: ORM, Middleware ve DRF Derinlemesine İnceleme
Django mülakat soruları: select_related ve prefetch_related ile ORM optimizasyonu, middleware mimarisi ve Django REST Framework serializer performansı, izinler ve sayfalama kalıpları.

Django ve Python Mulakat Sorulari: 2026'nin En Onemli 25 Sorusu
Django ve Python mulakatlarinda en sik sorulan 25 soru. ORM, gorunumler, middleware, DRF, sinyaller ve optimizasyon detayli cevaplar ve kod ornekleriyle.

Django ORM: maksimum performans için sorgu optimizasyonu
Django ORM sorgularını optimize etmek için kapsamlı rehber. select_related, prefetch_related, indeksler, N+1 sorunu analizi ve yüksek performanslı uygulamalar için ileri teknikler.