Django URL Yapısı: Reverse, Redirect ve Namespace Kullanımı
Django'da URL yönetimi, uygulamanızın hem güvenliği hem de kullanıcı deneyimi (UX) için kritik öneme sahiptir. Kodun içine URL'leri "hardcoded" (el ile sabit) yazmak yerine, Django'nun sunduğu reverse ve redirect araçlarını kullanmak işleri çok daha esnek hale getirir.
1. Django reverse Nedir?
reverse, Django'nun URL tersine çözümleme (URL reversing) mekanizmasıdır. Basitçe ifade etmek gerekirse: Siz Django'ya URL'nin ismini (name) verirsiniz, o size o isme karşılık gelen URL yolunu (string) verir.
Neden Kullanırız?
Eğer projenizde /blog/makale-detay/5/ şeklinde bir URL yapısı varsa ve ileride bunu /icerik/detay/5/ olarak değiştirmeye karar verirseniz, projenin her yerinde tek tek arama yapmanıza gerek kalmaz. Sadece urls.py içinde değişikliği yaparsınız, reverse otomatik olarak yeni yolu bulur.
Kullanım Şekli:
from django.urls import reverse
# Basit kullanım
url = reverse('home') # Çıktı: '/'
# Dinamik (Argümanlı) kullanım
url = reverse('post-detail', args=[5]) # Çıktı: '/post/5/'
# Keyword (Anahtar Kelime) ile kullanım
url = reverse('archive', kwargs={'year': 2024, 'month': 'february'})
2. Django redirect Nedir?
redirect, kullanıcıyı bir HTTP yanıtı (HttpResponseRedirect) ile başka bir sayfaya yönlendirmek için kullanılır.
redirect fonksiyonu aslında arka planda reverse fonksiyonunu da kullanabilir. Yani ona bir URL ismi verdiğinizde, o önce yolu bulur, sonra kullanıcıyı oraya gönderir.
Kullanım Senaryoları:
Kullanıcı bir formu başarıyla doldurduğunda "Teşekkürler" sayfasına göndermek.
Giriş yapmamış bir kullanıcıyı "Login" sayfasına yönlendirmek.
Kullanım Şekli:
from django.shortcuts import redirect
def my_view(request):
# ... işlemler ...
return redirect('home') # URL ismine yönlendirme
3. reverse ve redirect Arasındaki Farklar
Birçok yeni geliştirici bu ikisini karıştırır. Aralarındaki temel fark şudur:
| Özellik | reverse | redirect |
| Döndürdüğü Değer | Bir string (Örn: "/hakkimizda/") | Bir HttpResponse (Yönlendirme yanıtı) |
| Kullanım Amacı | URL yolunu hesaplamak/bulmak. | Kullanıcıyı başka bir sayfaya fiilen göndermek. |
| Nerede Kullanılır? | View'lar içinde, modellerde (get_absolute_url) veya testlerde. | Sadece View (Görünüm) fonksiyonlarının sonunda return ile. |
4. Uygulamalı Örnek: Bir Form İşleme
Diyelim ki bir blog yazısı oluşturma sayfanız var:
from django.shortcuts import render, redirect
from django.urls import reverse
from .models import Post
def create_post(request):
if request.method == 'POST':
# Formun kaydedildiğini varsayalım
new_post = Post.objects.create(title=request.POST.get('title'))
# 1. Senaryo: redirect kullanımı (En yaygın olan)
# Kullanıcıyı detay sayfasına gönderiyoruz
return redirect('post-detail', pk=new_post.pk)
return render(request, 'create_post.html')
def delete_post(request, pk):
# 2. Senaryo: reverse kullanımı
# Bazen URL'yi sadece bir değişkene atayıp başka bir yerde kullanmak istersiniz
success_url = reverse('home')
Post.objects.get(pk=pk).delete()
return redirect(success_url)
5. İleri Seviye İpucu: Modellerde get_absolute_url
Django'da en iyi pratiklerden biri, modelin kendi içine reverse kullanarak bir metod tanımlamaktır. Bu sayede redirect(post_nesnesi) dediğinizde Django nereye gideceğini otomatik anlar.
from django.db import models
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=100)
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
# View içinde artık sadece bunu yapmanız yeterlidir:
# return redirect(post_instance)
Özetle:
URL'nin ismini biliyorsunuz ama string haline (yoluna) ihtiyacınız varsa:
reversekullanın.Kullanıcının tarayıcısını başka bir sayfaya uçurmak istiyorsanız:
redirectkullanın.
Django Redirect ve reverse
(URL Yönetimi ve Yönlendirme Rehberi)
1. Giriş: Neden Redirect ve reverse?
Django projelerinde:
Bir form gönderildikten sonra başka bir sayfaya gitmek
URL’leri sabit yazmak yerine merkezi ve güvenli şekilde yönetmek
URL değiştiğinde tüm projeyi bozmamak
için redirect ve reverse kullanılır.
🎯 Amaç: URL’leri koddan bağımsız, sürdürülebilir ve güvenli hale getirmek
2. redirect Nedir?
redirect, kullanıcıyı başka bir URL’ye yönlendirmek için kullanılır.
📦 Bulunduğu yer:
from django.shortcuts import redirect
3. redirect Kullanım Türleri
3.1 Sabit URL’ye Redirect
def home(request):
return redirect('/login/')
📌 Dezavantaj:
URL değişirse tüm kodlar bozulur ❌
3.2 URL Name (Önerilen Kullanım)
def home(request):
return redirect('login')
📌 Avantaj:
URL değişse bile çalışır
Django’nun en iyi pratiği ✅
3.3 Parametreli Redirect
def profile_redirect(request):
return redirect('profile', username='nuri')
URL yapısı:
path('profile/<str:username>/', views.profile, name='profile')
3.4 Model Nesnesi ile Redirect
def post_detail(request, id):
post = Post.objects.get(id=id)
return redirect(post)
Model içinde:
def get_absolute_url(self):
return reverse('post_detail', args=[self.id])
4. reverse Nedir?
reverse, URL name → gerçek URL dönüşümü yapar.
📦 Bulunduğu yer:
from django.urls import reverse
5. reverse Kullanımı
5.1 Basit reverse
url = reverse('login')
Çıktı:
/login/
5.2 Parametreli reverse
reverse('profile', kwargs={'username': 'nuri'})
Çıktı:
/profile/nuri/
5.3 redirect + reverse Birlikte
def go_profile(request):
return redirect(reverse('profile', kwargs={'username': 'nuri'}))
📌 Not:redirect() zaten reverse işlemi yaptığı için genelde gerekmez.
6. reverse_lazy Nedir?
Class Based View (CBV) kullanırken lazy (gecikmeli) URL çözümü gerekir.
from django.urls import reverse_lazy
Kullanım:
class LoginView(FormView):
success_url = reverse_lazy('home')
📌 reverse() burada hata verir ❌
📌 reverse_lazy() güvenlidir ✅
7. redirect vs reverse Karşılaştırması
| Özellik | redirect | reverse |
|---|---|---|
| Yönlendirme yapar | ✅ | ❌ |
| URL üretir | ❌ | ✅ |
| View içinde kullanılır | ✅ | ✅ |
| CBV uyumlu | ✅ | reverse_lazy |
| Kullanıcıyı taşır | ✅ | ❌ |
8. Template (HTML) İçinde reverse
Template’lerde {% url %} etiketi kullanılır.
<a href="{% url 'profile' username='nuri' %}">
Profil
</a>
📌 Bu yapı reverse’in template karşılığıdır.
9. Gerçek Hayat Senaryosu (Form Sonrası Redirect)
def register(request):
if request.method == 'POST':
# kayıt işlemleri
return redirect('login')
return render(request, 'register.html')
🎯 Amaç:
Sayfa yenilenince tekrar POST olmasın
PRG Pattern (Post → Redirect → Get)
10. En İyi Uygulamalar (Best Practices)
✅ URL’leri asla sabit yazma
✅ Her zaman name= kullan
✅ CBV → reverse_lazy
✅ Template → {% url %}
❌ /login/ gibi hard-coded URL kullanma
11. Sık Yapılan Hatalar
❌ URL name yanlış yazmak
❌ Parametre eksik vermek
❌ reverse yerine string URL kullanmak
❌ CBV’de reverse kullanmak
12. Özet
redirect → Kullanıcıyı başka sayfaya götürür
reverse → URL name’den gerçek URL üretir
reverse_lazy → CBV için güvenli çözümdür
Django’da URL yönetiminin bel kemiğidir
Mini Django Projesi
Login → Dashboard Yönlendirmesi (redirect & reverse)
🎯 Amaç
reverseile URL üretmekredirectile kullanıcıyı yönlendirmekPOST → Redirect → GET mantığını görmek
Framework: Django
1️⃣ Proje Yapısı
redirect_project/
│
├── manage.py
├── redirect_project/
│ ├── settings.py
│ ├── urls.py
│
└── accounts/
├── views.py
├── urls.py
└── templates/
└── accounts/
├── login.html
└── dashboard.html
2️⃣ Proje ve App Oluşturma
django-admin startproject redirect_project
cd redirect_project
python manage.py startapp accounts
settings.py içine ekle:
INSTALLED_APPS = [
...
'accounts',
]
3️⃣ URL Yapısı
📄 redirect_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('accounts.urls')),
]
📄 accounts/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.login_view, name='login'),
path('dashboard/', views.dashboard, name='dashboard'),
]
📌 Buradaki name alanları reverse & redirect’in kalbidir
4️⃣ Views (redirect & reverse burada)
📄 accounts/views.py
from django.shortcuts import render, redirect
from django.urls import reverse
def login_view(request):
if request.method == 'POST':
username = request.POST.get('username')
# reverse → URL üretir
dashboard_url = reverse('dashboard')
# redirect → kullanıcıyı taşır
return redirect(dashboard_url)
return render(request, 'accounts/login.html')
def dashboard(request):
return render(request, 'accounts/dashboard.html')
📌 Burada olan şey:
URL name → reverse → gerçek URL → redirect → yönlendirme
5️⃣ Template Dosyaları
📄 login.html
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Giriş Yap</h2>
<form method="post">
{% csrf_token %}
<input type="text" name="username" placeholder="Kullanıcı Adı">
<button type="submit">Giriş</button>
</form>
</body>
</html>
📄 dashboard.html
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<h1>Hoş Geldin 🎉</h1>
<a href="{% url 'login' %}">Çıkış</a>
</body>
</html>
📌 {% url %} → template içindeki reverse
6️⃣ Çalışma Akışı (Çok Önemli)
/login/ (GET)
↓
Form Gönderilir (POST)
↓
reverse('dashboard')
↓
redirect('/dashboard/')
↓
/dashboard/ (GET)
🎯 PRG Pattern (Post → Redirect → Get)
➡️ Sayfa yenilendiğinde form tekrar gönderilmez
7️⃣ redirect vs reverse Nerede Kullanıldı?
| Yer | Kullanım |
|---|---|
| urls.py | name='dashboard' |
| views.py | reverse('dashboard') |
| views.py | redirect(dashboard_url) |
| template | {% url 'login' %} |
8️⃣ Öğretmen / Ders İçin Bonus Görevler
🧠 Öğrenciye sorulabilecek sorular:
reverseneden string URL yerine kullanılır?redirect('/dashboard/')yazarsak ne kaybederiz?Template’te
{% url %}neyin karşılığıdır?Bu projede PRG hangi satırda uygulanıyor?
9️⃣ Mini Geliştirme Önerileri
🔐 Login kontrolü ekle
🧩
reverse_lazyile CBV versiyonunu yaz🎨 Bootstrap ekle
🚫 Giriş yapmadan dashboard’a girişi engelle
10️⃣ Özet
✅ reverse → URL üretir
✅ redirect → kullanıcıyı taşır
✅ Template {% url %} → reverse’in HTML hali
✅ Bu mini proje → konuyu tam öğretir
Hazırladığımız Mini Django projesine, Django’nun yerleşik Authentication (login–logout) sistemini adım adım, eğitim + proje mantığıyla ekliyorum.
Framework: Django
Mini Projeye Auth (Login – Logout) Ekleme
(redirect & reverse ile tam uyumlu)
🎯 Hedefler
Django auth kullanarak gerçek kullanıcı girişi
Login sonrası dashboard’a redirect
Logout sonrası login sayfasına redirect
Giriş yapılmadan dashboard’a erişimi engellemek
1️⃣ Django Auth Hazır mı?
Evet ✅
Django kuruluysa şu paketler zaten hazırdır:
django.contrib.auth
django.contrib.sessions
settings.py içinde kontrol et:
INSTALLED_APPS = [
...
'django.contrib.auth',
'django.contrib.sessions',
]
2️⃣ URLs – Login & Logout
📄 accounts/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.login_view, name='login'),
path('logout/', views.logout_view, name='logout'),
path('dashboard/', views.dashboard, name='dashboard'),
]
3️⃣ Views – Gerçek Auth İşlemleri
📄 accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.urls import reverse
def login_view(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('dashboard')
else:
return render(request, 'accounts/login.html', {
'error': 'Kullanıcı adı veya şifre hatalı'
})
return render(request, 'accounts/login.html')
@login_required(login_url='login')
def dashboard(request):
return render(request, 'accounts/dashboard.html')
def logout_view(request):
logout(request)
return redirect('login')
📌 Burada neler var?
authenticate()→ kullanıcıyı doğrularlogin()→ session başlatırlogout()→ session kapatır@login_required→ yetkisiz erişimi engellerredirect('dashboard')→ reverse + redirect birlikte
4️⃣ Template – Login Sayfası
📄 login.html
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Giriş Yap</h2>
{% if error %}
<p style="color:red;">{{ error }}</p>
{% endif %}
<form method="post">
{% csrf_token %}
<input type="text" name="username" placeholder="Kullanıcı Adı" required>
<br><br>
<input type="password" name="password" placeholder="Şifre" required>
<br><br>
<button type="submit">Giriş</button>
</form>
</body>
</html>
5️⃣ Template – Dashboard (Auth Kontrollü)
📄 dashboard.html
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<h1>Hoş Geldin {{ request.user.username }} 🎉</h1>
<p>Burası sadece giriş yapan kullanıcılar içindir.</p>
<a href="{% url 'logout' %}">Çıkış Yap</a>
</body>
</html>
📌 request.user → auth sistemi tarafından otomatik gelir
6️⃣ Kullanıcı Oluşturma (Admin)
python manage.py createsuperuser
➡️ Kullanıcı adı & şifre belirle
➡️ Bu bilgilerle login ol
7️⃣ Çalışma Akışı (Çok Önemli)
/login/
↓
authenticate()
↓
login()
↓
redirect('dashboard')
↓
/dashboard/ (korumalı)
Çıkış:
logout()
↓
redirect('login')
🎯 Gerçek hayattaki tüm Django projelerinin temeli
8️⃣ Güvenlik & Best Practice
✅ @login_required kullan
✅ URL’leri name= ile yönet
✅ redirect + reverse tercih et
❌ Şifreyi manuel kontrol etme
❌ Session’ı kendin yazma
9️⃣ Öğrenci / Yazılı Soruları (Hazır)
authenticate()ne yapar?login()ile session arasındaki ilişki nedir?@login_requiredneden önemlidir?Logout işleminden sonra neden redirect yapılır?
{% url 'logout' %}neyin karşılığıdır?
🔟 Bu Proje Artık Ne Oldu?
✅ Gerçek login–logout sistemi
✅ Yetkilendirme (authorization)
✅ redirect & reverse uygulamalı
✅ Pardus / ders / sınav uyumlu
✅ Gerçek Django projelerine %100 geçiş yapılabilir
Django projeleri büyüdükçe, farklı uygulamalar (apps) içinde aynı isimde URL'ler tanımlamanız kaçınılmaz hale gelir. Örneğin, hem bir blog uygulamanız hem de bir video uygulamanız varsa, her ikisinde de bir detail (detay) sayfası olabilir.
İşte burada Namespace (İsim Alanı) devreye girer. Bu, URL'lerinizi paketleyerek birbirleriyle karışmasını önleyen bir "soyadı" sistemi gibidir.
1. Namespace Neden Gereklidir?
Eğer iki farklı urls.py dosyasında da name='detail' tanımı varsa, Django en son yüklenen URL'yi baz alır. Bu da blog:detail yerine yanlışlıkla video:detail sayfasına gitmenize neden olur. Namespace kullanarak "Blog uygulamasındaki detay sayfasına git" demiş olursunuz.
2. Namespace Nasıl Tanımlanır?
Namespace tanımlamanın en yaygın ve doğru yolu, ana urls.py dosyasında include fonksiyonunu kullanırken namespace parametresini belirtmektir.
Ana urls.py (Proje Dizini)
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls', namespace='blog')),
path('videolar/', include('video.urls', namespace='video')),
]
Uygulama urls.py (blog/urls.py)
Uygulama düzeyinde de bir app_name değişkeni tanımlamak en iyi pratiktir:
from django.urls import path
from . import views
app_name = 'blog' # Bu satır kritik!
urlpatterns = [
path('<int:pk>/', views.post_detail, name='detail'),
]
3. Namespace ile reverse ve redirect Kullanımı
Artık URL isminin önüne uygulama adını ve iki nokta üst üste (:) işaretini eklemeniz gerekir.
Python Kodunda (View'lar içinde):
from django.shortcuts import redirect
from django.urls import reverse
def some_view(request):
# Reverse ile kullanımı
blog_url = reverse('blog:detail', kwargs={'pk': 5})
# Redirect ile kullanımı
return redirect('blog:detail', pk=10)
HTML Şablonlarında (Template):
<a href="{% url 'blog:detail' pk=post.id %}">Yazıyı Oku</a>
4. Gerçek Hayat Senaryosu: "Aynı İsimli View" Karmaşası
Diyelim ki bir e-ticaret siteniz var:
products:index(Ürün listesi)orders:index(Sipariş listesi)
Eğer namespace kullanmasaydınız, her iki uygulama için de name='index' tanımlayacaktınız. Django hangisini çağıracağını şaşıracak ve muhtemelen her zaman en son tanımlanan uygulamaya yönlendirecekti. Namespace sayesinde bu belirsizlik ortadan kalkar.
5. Dinamik Instance Namespace (Gelişmiş)
Bazen aynı uygulamayı iki farklı URL altında çalıştırmak isteyebilirsiniz (Örneğin; hem /blog/ hem de /haberler/ aynı blog uygulamasını kullansın ama farklı içerik göstersin). Bu durumda include içindeki namespace değeri dinamikleştirilebilir. Ancak standart projelerde yukarıdaki app_name yöntemi %99 oranında yeterlidir.
Özet:
app_name: Uygulamanın içindekiurls.py'da tanımlanır.namespace: Anaurls.py'daincludeedilirken verilir.Kullanım:
'uygulama_adı:url_adı'formatındadır.
Harika! get_absolute_url, Django’nun en zarif ve "pro" özelliklerinden biridir. Bu metod, bir model nesnesinin "kendi URL'sini bilmesini" sağlar. Namespace yapısıyla birleştiğinde ise tadından yenmez.
Neden buna ihtiyaç duyarız? Çünkü projenin her yerinde (şablonlar, view'lar, admin paneli) URL'yi manuel oluşturmak yerine, nesneye "senin adresin neresi?" diye sormak çok daha güvenlidir.
1. Modelde get_absolute_url Tanımlama
Diyelim ki bir Post (Yazı) modeliniz var ve bu model blog namespace'i altında çalışıyor.
from django.db import models
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
def __str__(self):
return self.title
# Sihirli metodumuz burada:
def get_absolute_url(self):
# Namespace: blog, URL Name: detail
return reverse('blog:detail', kwargs={'slug': self.slug})
2. Neden Namespace ile reverse Kullandık?
Buradaki reverse('blog:detail', ...) kullanımı sayesinde:
Hata Payı Sıfırlanır: URL yapısını
urls.pyiçinde değiştirseniz bile (örneğin/yazi/yerine/makale/yapsanız da), bu metod doğru linki üretmeye devam eder.Okunabilirlik Artar: Kodun içinde karmaşık URL stringleri dolaşmaz.
3. Kullanım Alanları (İşte Asıl Kolaylık Burada!)
get_absolute_url tanımladığınızda Django size üç büyük avantaj sağlar:
A. Şablonlarda (Template) Kullanım
Artık uzun uzun {% url ... %} yazmanıza gerek kalmaz. Sadece nesnenin metodunu çağırırsınız:
<a href="{% url 'blog:detail' slug=post.slug %}">Oku</a>
<a href="{{ post.get_absolute_url }}">Oku</a>
B. View İçinde redirect ile Kullanım
Django'nun redirect fonksiyonu çok akıllıdır. Eğer ona bir model nesnesi verirseniz, o nesnenin get_absolute_url metodu olup olmadığına bakar. Varsa, kullanıcıyı otomatik o adrese gönderir.
from django.shortcuts import redirect
def post_create_view(request):
# ... form işlemleri ...
if form.is_valid():
new_post = form.save()
# Sadece nesneyi veriyoruz, gerisini Django hallediyor!
return redirect(new_post)
C. Django Admin Paneli
Bu metodu tanımladığınızda, Django Admin panelinde yazı detayına girdiğinizde sağ üst köşede "Sitede Görüntüle" (View on site) butonu belirir. Bu buton sizi doğrudan yazının canlı sayfasına götürür.
4. Namespace + get_absolute_url Akış Şeması
Bu yapıyı kurduğunuzda projenizdeki veri akışı şu şekilde olur:
Veritabanı:
Postnesnesi (ID: 5, Slug: 'django-dersi')Model Metodu:
post.get_absolute_url()çağrılır.Reverse: Django
blog:detailismine bakar,urls.py'dan/blog/django-dersi/sonucunu üretir.Sonuç: Kullanıcı veya şablon doğru adresi alır.
Küçük Bir İpucu: redirect İçin Kestirme Yollar
Unutmayın, redirect şu üçünü de kabul eder:
Model nesnesi:
redirect(my_post)(Metod tanımlıysa)URL ismi:
redirect('blog:detail', slug='test')Ham URL:
redirect('/blog/test/')
Her zaman ilk iki seçeneği tercih etmek, projenizin bakımını (maintenance) inanılmaz kolaylaştıracaktır.
Yorumlar
Yorum Gönder