JWT (JSON Web Token) ile Kimlik Doğrulama
Herkese merhaba! Bugün uygulamalarımızın arka planında dönen çok havalı ve bir o kadar da önemli bir konuyu öğreneceğiz: Kimlik Doğrulama (Authentication). Özellikle de modern web ve mobil uygulamaların vazgeçilmezi olan JWT (JSON Web Token) teknolojisini keşfedeceğiz.
Arka uçta (Backend) Django, ön uçta (Frontend) Flutter kullanarak bu sistemi nasıl kuracağımıza adım adım bakacağız. Hazırsanız başlayalım!
JWT (JSON Web Token) Nedir?
Diyelim ki harika bir eğlence parkına gittiniz. Girişte biletinizi veya kimliğinizi gösteriyorsunuz ve size bileğinize takmanız için bir bileklik veriyorlar. Artık parktaki her oyuncağa binerken tekrar tekrar kimlik göstermenize gerek yok; sadece bilekliğinizi göstermeniz yeterli!
İşte JWT tam olarak bu bilekliktir.
Giriş Yaparsınız: Kullanıcı adı ve şifrenizi (kimliğinizi) Django sunucusuna gönderirsiniz.
Bilekliği Alırsınız: Eğer bilgileriniz doğruysa, Django size özel bir JWT (bileklik) oluşturur ve gönderir.
Flutter'da Saklarsınız: Flutter uygulamamız bu bilekliği alır ve telefonun hafızasına (örneğin
shared_preferencesile) kaydeder.İçeriğe Ulaşırsınız: Artık sunucudan özel bir veri istediğinizde (mesela profil bilgileri), şifrenizi değil, bu JWT'yi gönderirsiniz. Django bilekliğe bakar, "Tamam, bu kişiyi tanıyorum" der ve veriyi verir.
JWT'nin Yapısı
Bir JWT, aralarına nokta (.) konulmuş üç parçadan oluşur:
Header (Başlık): Biletin türü ve şifreleme algoritması yazar.
Payload (Yük): Kullanıcının ID'si, yetkileri gibi zararsız bilgiler burada durur.
Signature (İmza): Bu biletin sahte olmadığını, gerçekten Django sunucumuz tarafından üretildiğini kanıtlayan mühürdür.
1. Aşama: Django Sunucusunu Hazırlama (Güvenlik Kapısı)
Öncelikle Django projemize JWT yeteneği kazandırmalıyız. Bunun için djangorestframework-simplejwt paketini kullanacağız.
Adım 1: Kurulum
Terminali açın ve sanal ortamınız aktifken şu komutları yazın:
pip install djangorestframework
pip install djangorestframework-simplejwt
Adım 2: Ayarlar (settings.py)
Django'ya bu yeni araçları kullanmasını söylemeliyiz. settings.py dosyanızı açın ve aşağıdaki eklemeleri yapın:
INSTALLED_APPS = [
# ... diğer uygulamalarınız
'rest_framework',
'rest_framework_simplejwt',
]
# REST Framework'e kimlik doğrulama için JWT kullanacağını söylüyoruz:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
Adım 3: Rotaları Belirleme (urls.py)
Kullanıcıların gelip biletlerini (Token) alabilecekleri kapıları (URL'leri) açmamız gerekiyor. Projenizin ana urls.py dosyasını şöyle düzenleyin:
from django.contrib import admin
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView, # Giriş yapıp token alma görünümü
TokenRefreshView, # Süresi biten token'ı yenileme görünümü
)
urlpatterns = [
path('admin/', admin.site.urls),
# Flutter'dan kullanıcı adı ve şifre buraya gönderilecek:
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
# Biletin süresi dolarsa yenisini buradan alacağız:
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
Harika! Artık Django sunucumuz gelen kullanıcı adı ve şifreleri kontrol edip onlara Access (Erişim) ve Refresh (Yenileme) token'ları verebilir duruma geldi.
2. Aşama: Flutter Uygulamasını Hazırlama (Müşteri)
Şimdi Flutter tarafına geçiyoruz. Kullanıcıdan bilgileri alıp Django'ya göndereceğiz, gelen bilekliği (Token) alıp saklayacağız.
Adım 1: Gerekli Paketleri Yükleme
Flutter projenizin terminalinde şu komutu çalıştırarak internete çıkmak için http ve token'ı telefona kaydetmek için shared_preferences paketlerini ekleyin:
flutter pub add http shared_preferences
Adım 2: Giriş Yapma Fonksiyonu (Login)
Flutter'da bir servis dosyası oluşturalım. Bu fonksiyon, kullanıcının girdiği bilgileri Django'ya gönderecek.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
// Django sunucunuzun adresi (Emülatör için localhost yerine 10.0.2.2 kullanılır)
final String baseUrl = 'http://10.0.2.2:8000/api';
Future<bool> login(String username, String password) async {
// Django'daki token alma adresine gidiyoruz
final response = await http.post(
Uri.parse('$baseUrl/token/'),
body: {
'username': username,
'password': password,
},
);
// Eğer sunucu "Tamamdır, bilgiler doğru" (200) derse:
if (response.statusCode == 200) {
// Gelen JSON verisini parçala
var data = jsonDecode(response.body);
// Access token'ı al (Bilekliğimiz)
String accessToken = data['access'];
// Token'ı telefonun hafızasına kaydet ki uygulama kapanınca silinmesin
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('token', accessToken);
print("Giriş başarılı! Bileklik alındı.");
return true;
} else {
print("Hata: Kullanıcı adı veya şifre yanlış!");
return false;
}
}
}
Adım 3: Bileklikle İçeri Girme (Yetkili İstek Atma)
Diyelim ki girişi yaptık ve token'ı kaydettik. Şimdi Django'dan sadece giriş yapmış kişilerin görebileceği özel bir veri (mesela not defteri veya profil) isteyeceğiz. İstek atarken "Header" (Başlık) kısmına bilekliğimizi iliştirmemiz gerekiyor.
Future<void> getOzelVeriler() async {
// Önce telefondaki çekmeceden (hafızadan) kaydettiğimiz bilekliği alalım
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
if (token == null) {
print("Önce giriş yapmalısın!");
return;
}
// Şimdi Django'ya istek atıyoruz ama bu sefer bilekliği gösteriyoruz!
final response = await http.get(
Uri.parse('$baseUrl/ozel-veriler/'),
headers: {
'Authorization': 'Bearer $token', // İşte kritik nokta burası!
},
);
if (response.statusCode == 200) {
print("Başarılı! Veriler: ${response.body}");
} else {
print("Bu veriye ulaşmaya yetkiniz yok veya token süresi dolmuş.");
}
}
Özetle Neler Yaptık?
Öğrendik ki JWT, bizi sürekli şifre yazma derdinden kurtaran dijital bir bilekliktir.
Django (Backend) tarafında bu bilekliği üretecek ve kontrol edecek sistemi kurduk.
Flutter (Frontend) tarafında ise kullanıcıdan şifre alıp bilekliği talep ettik ve sonraki işlemlerimiz için bu bilekliği güvenli bir şekilde cebimize (Shared Preferences) koyduk.
Yazılım dünyasında bu sistem, devasa uygulamalardan tutun küçük girişimlere kadar her yerde kullanılır. Siz de kendi projelerinizde bu yapıyı kurarak uygulamalarınızı profesyonel bir seviyeye taşıyabilirsiniz! İyi kodlamalar! 🚀
Öğrencilerinizle laboratuvardaki Pardus makinelerinizde veya kendi bilgisayarlarınızda baştan sona çalıştırabileceğiniz, hem arka ucu hem de ön ucu içeren tam bir "Gizli Notlar" (Secret Notes) uygulaması hazırlayalım.
Bu uygulama, öğrencilerin kendi kullanıcı adları ve şifreleriyle giriş yapıp (JWT biletini alıp), sadece kendilerine ait notları görebilecekleri temel bir sistem olacak.
BÖLÜM 1: Arka Uç (Django)
Öncelikle bir Django projesi (backend) ve bir uygulama (notes_app) oluşturduğunuzu varsayarak en temel dosyaları yazıyoruz. (Önceki mesajdaki JWT ayarlarının settings.py içinde yapıldığını unutmayın).
1. notes_app/models.py (Veritabanı Tasarımı)
Öğrencilerin notlarını tutacağımız tabloyu oluşturuyoruz. Her not, bir kullanıcıya ait olacak.
from django.db import models
from django.contrib.auth.models import User
class Note(models.Model):
# Bu not hangi öğrenciye (kullanıcıya) ait?
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, verbose_name="Başlık")
content = models.TextField(verbose_name="Not İçeriği")
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
2. notes_app/serializers.py (Veri Çevirmenimiz)
Veritabanındaki Python nesnelerini, Flutter'ın anlayacağı JSON formatına çeviriyoruz.
from rest_framework import serializers
from .models import Note
class NoteSerializer(serializers.ModelSerializer):
class Meta:
model = Note
fields = ['id', 'title', 'content', 'created_at']
3. notes_app/views.py (Güvenlik Kontrolü ve İşlemler)
Sadece "bilekliği (JWT Token) olanlar" bu görünüme erişip kendi notlarını görebilir.
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from .models import Note
from .serializers import NoteSerializer
class NoteListCreate(generics.ListCreateAPIView):
serializer_class = NoteSerializer
permission_classes = [IsAuthenticated] # GÜVENLİK KAPISI: Bilekliği olmayan giremez!
# Sadece giriş yapan kullanıcının kendi notlarını getirir:
def get_queryset(self):
return Note.objects.filter(user=self.request.user)
# Yeni not eklenirken, notun sahibini otomatik olarak giriş yapan kişi yapar:
def perform_create(self, serializer):
serializer.save(user=self.request.user)
4. notes_app/urls.py (Rotalar)
from django.urls import path
from .views import NoteListCreate
from rest_framework_simplejwt.views import TokenObtainPairView
urlpatterns = [
# Bileklik (Token) Alma Kapısı
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
# Notları Görme ve Yazma Kapısı (Bileklik zorunlu)
path('api/notes/', NoteListCreate.as_view(), name='note_list_create'),
]
(Not: Bu aşamada Django'da python manage.py makemigrations, migrate ve createsuperuser komutlarını çalıştırarak test için bir kullanıcı oluşturmayı unutmayın. Sonrasında python manage.py runserver ile sunucuyu ayağa kaldırın.)
BÖLÜM 2: Ön Uç (Flutter)
Öğrencilerin telefonlarında veya emülatörlerinde göreceği arayüz. http ve shared_preferences paketlerini pubspec.yaml dosyanıza eklediğinizden emin olun.
lib/main.dart
Öğrencilerinizle Sınıfta Denerken İpuçları:
IP Adresi: Eğer Django sunucusunu Pardus bilgisayarınızda (örneğin öğretmen bilgisayarında) çalıştırıyorsanız ve öğrenciler kendi bilgisayarlarındaki Flutter web veya emülatörden bağlanacaksa, Flutter kodundaki
10.0.2.2yerine laboratuvar ağınızdaki yerel IP adresinizi (Örn:192.168.1.100) yazmalarını söyleyebilirsiniz.CORS Ayarları: Eğer Flutter'ı Web üzerinden çalıştırarak test edecekseniz, Django tarafında
django-cors-headerspaketini kurup Flutter'ın istek yapmasına izin vermeyi unutmayın.
Django Kaynak Kod: https://github.com/nuritiras/secret.git
Flutter Kaynak Kod : https://github.com/nuritiras/flutter_secret_notes.git
JWT Nedir?
JWT, kullanıcı doğrulamasını token bazlı yapan bir yöntemdir. Her istekte kullanıcı adı ve şifre gönderilmez, bunun yerine token kullanılır.
JWT yapısı:
header.payload.signature
Header → Token türü ve algoritma
Payload → Kullanıcı bilgileri (user_id, email vs.)
Signature → Token’ın doğruluğunu garantiler
DRF ile JWT Kurulumu
Paketleri yükleyin:
pip install djangorestframework-simplejwt
settings.pyyapılandırması:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}
URL'leri ekleyin:
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
Kullanımı:
/api/token/→POSTile{ "username": "user", "password": "pass" }/api/token/refresh/→POSTile{ "refresh": "token" }
Not: JWT, session bazlı auth yerine kullanıldığında özellikle mobile app ve SPA (React/Flutter) projelerinde avantajlıdır.
2. Authentication (Kimlik Doğrulama)
DRF’de authentication, her istekte kullanıcının kim olduğunu doğrulama işlemi sağlar.
DRF’de Mevcut Authentication Türleri
SessionAuthentication → Django session ile tarayıcı tabanlı.
BasicAuthentication → HTTP Basic Auth (test amaçlı).
TokenAuthentication → DRF’nin default token sistemi.
JWTAuthentication → Modern ve mobil/SPA uyumlu.
Örnek View:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class ProfileView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({
"user": request.user.username,
"email": request.user.email
})
Burada
IsAuthenticatedsayesinde sadece giriş yapmış kullanıcılar erişebilir.
3. Permissions (İzinler)
Permissions, hangi kullanıcı hangi kaynağa erişebilir sorusunu kontrol eder.
DRF’de hazır permission sınıfları
| Permission | Açıklama |
|---|---|
AllowAny | Herkes erişebilir |
IsAuthenticated | Sadece giriş yapmış kullanıcı |
IsAdminUser | Sadece admin kullanıcı |
IsAuthenticatedOrReadOnly | Okuma herkes, yazma giriş yapmış kullanıcı |
Custom Permission Örneği
from rest_framework.permissions import BasePermission
class IsOwner(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
has_object_permission→ Belirli objeler için kontrol sağlar.Kullanımı:
class ArticleDetail(APIView):
permission_classes = [IsOwner]
def get_object(self, pk):
return Article.objects.get(pk=pk)
4. JWT + Custom Claims
JWT payload’ına özel veri ekleyebilirsiniz:
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
token['is_admin'] = user.is_staff
return token
urls.py:
from .views import MyTokenObtainPairView
path('api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
5. JWT + Refresh Token Mantığı
Access Token: kısa ömürlü (5–15 dk)
Refresh Token: uzun ömürlü (7–30 gün), access token yenilemek için kullanılır.
Kullanıcı, refresh token ile her zaman yeni access token alabilir.
6. Örnek İleri Seviye View
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from .models import Article
from .serializers import ArticleSerializer
class ArticleListCreateView(generics.ListCreateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticated]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
Burada sadece giriş yapmış kullanıcı yeni içerik ekleyebilir.
perform_createile otomatik owner ataması yapılır.
7. Güvenlik İpuçları
JWT Secret Key’i güçlü seçin:
settings.py→SECRET_KEYHTTPS kullanın: Token’lar şifrelenmeden gönderilmemeli
Short-lived Access Token + Long-lived Refresh Token
Blacklist özelliğini aktif edin (
rest_framework_simplejwt.token_blacklist)
8. Profesyonel Diyagram
[Client] <--JWT--> [DRF API]
| |
|--Login------------>|
|<--Access/Refresh-- |
|--API Request------>|
|--JWT Token Header->|
|<--Data------------ |
Client → React, Flutter veya Postman olabilir
DRF → JWT ile auth kontrolü
Token, header Authorization:
Bearer <token>şeklinde gönderilir.
1️⃣ Proje Yapısı
school_api/ # Django projesi
├─ manage.py
├─ school_api/ # Settings
│ ├─ settings.py
│ ├─ urls.py
│ └─ wsgi.py
├─ users/ # Kullanıcı uygulaması
│ ├─ models.py
│ ├─ serializers.py
│ ├─ views.py
│ ├─ urls.py
│ └─ permissions.py
└─ articles/ # Örnek içerik uygulaması
├─ models.py
├─ serializers.py
├─ views.py
├─ urls.py
└─ permissions.py
2️⃣ settings.py – DRF ve JWT
INSTALLED_APPS = [
'rest_framework',
'rest_framework_simplejwt.token_blacklist',
'users',
'articles',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
3️⃣ Kullanıcı Modeli (users/models.py)
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
bio = models.TextField(blank=True, null=True)
def __str__(self):
return self.username
AUTH_USER_MODEL = 'users.CustomUser'ayarınısettings.py’ye eklemeyi unutmayın.
4️⃣ Kullanıcı Serializer (users/serializers.py)
from rest_framework import serializers
from .models import CustomUser
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ('id', 'username', 'email', 'bio')
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
return token
5️⃣ Kullanıcı Views (users/views.py)
from rest_framework import generics, permissions
from .models import CustomUser
from .serializers import UserSerializer, MyTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
# JWT login view
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
# Register view
class RegisterView(generics.CreateAPIView):
queryset = CustomUser.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.AllowAny]
# Profile view
class ProfileView(generics.RetrieveAPIView):
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
def get_object(self):
return self.request.user
6️⃣ Custom Permission (articles/permissions.py)
from rest_framework.permissions import BasePermission
class IsOwner(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.owner == request.user
7️⃣ Article Model & Serializer (articles/models.py & serializers.py)
# models.py
from django.db import models
from users.models import CustomUser
class Article(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
owner = models.ForeignKey(CustomUser, related_name='articles', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
read_only_fields = ('owner',)
8️⃣ Article Views (articles/views.py)
from rest_framework import generics
from .models import Article
from .serializers import ArticleSerializer
from .permissions import IsOwner
from rest_framework.permissions import IsAuthenticated
class ArticleListCreateView(generics.ListCreateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticated]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class ArticleDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsOwner]
9️⃣ URL Yapısı
# school_api/urls.py
from django.urls import path, include
urlpatterns = [
path('api/users/', include('users.urls')),
path('api/articles/', include('articles.urls')),
]
# users/urls.py
from django.urls import path
from .views import MyTokenObtainPairView, RegisterView, ProfileView
urlpatterns = [
path('login/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('register/', RegisterView.as_view(), name='register'),
path('profile/', ProfileView.as_view(), name='profile'),
]
# articles/urls.py
from django.urls import path
from .views import ArticleListCreateView, ArticleDetailView
urlpatterns = [
path('', ArticleListCreateView.as_view(), name='article_list_create'),
path('<int:pk>/', ArticleDetailView.as_view(), name='article_detail'),
]
🔹 ER Diyagramı
[CustomUser]
|--id
|--username
|--email
|--bio
|
| 1
| owns
| *
[Article]
|--id
|--title
|--content
|--owner_id (FK CustomUser)
|--created_at
CustomUser→Articlearasında bire çok ilişki.JWT Authentication → tüm endpointlerde token kontrolü.
IsOwner→ sadece sahip kullanıcı CRUD yapabilir.
💡 Bu yapı ile:
Kullanıcı kayıt, login ve profile görüntüleyebilir
JWT ile güvenli auth yapılır
Kullanıcı sadece kendi oluşturduğu içerikleri değiştirebilir
Admin veya diğer permission kuralları kolayca eklenebilir
🔹 Flutter + Django REST API: 10 Proje Fikri
Okul Yönetim Sistemi
Öğrenci, öğretmen, ders, sınav ve not yönetimi.
Kullanıcı tipine göre rol tabanlı yetkilendirme (Öğrenci / Öğretmen / Admin).
API: Öğrenci kayıt, not ekleme, ders listesi.
Sağlıklı Yaşam Takip Uygulaması
Adım sayacı, su tüketimi, kalori takibi.
Django API: Kullanıcı verileri CRUD, grafik verileri JSON olarak döndürme.
Kütüphane Yönetim Sistemi
Kitap ödünç alma/iade, stok yönetimi, kullanıcı bildirimleri.
API: Kitap listesi, ödünç alınan kitap, iade işlemleri.
E-Ticaret Mobil Uygulaması
Ürün listeleme, sepete ekleme, ödeme entegrasyonu.
API: Ürün CRUD, sipariş oluşturma, ödeme durum takibi.
Etkinlik Takip ve Rezervasyon Uygulaması
Kullanıcı etkinlik oluşturabilir ve rezervasyon yapabilir.
API: Etkinlik CRUD, katılım doğrulama.
Sosyal Medya Mini Uygulaması
Gönderi paylaşımı, yorum ve beğeni sistemi.
API: Kullanıcı profili, gönderi listesi, yorum ekleme.
Haber / Blog Uygulaması
Kategoriye göre haber / blog listeleme.
API: Haber CRUD, kategori filtreleme, detaylı haber görüntüleme.
Görev ve Proje Yönetim Uygulaması
Kullanıcı görev ekleyebilir, projelere atanabilir, durum güncelleyebilir.
API: Görev CRUD, proje bazlı filtreleme.
Online Anket / Quiz Uygulaması
Anket oluşturma, cevaplama ve sonuçları görüntüleme.
API: Anket CRUD, kullanıcı cevap takibi, sonuç istatistikleri.
Finans Takip / Bütçe Yönetimi
Gelir-gider takibi, kategori bazlı analiz.
API: Kullanıcı finans CRUD, aylık raporlar.
🔹 Flutter için Profesyonel API Mimarisi (Clean Architecture)
Clean Architecture, kodu katmanlara ayırarak yönetir ve test edilebilirliği artırır. Flutter + REST API için tipik yapı:
lib/
│
├─ data/ # Veri katmanı
│ ├─ models/ # JSON model sınıfları
│ ├─ repositories/ # API çağrıları ve veri çekme
│ └─ datasources/ # Remote (Django REST) ve local (SQLite, Hive) kaynaklar
│
├─ domain/ # İş mantığı
│ ├─ entities/ # Core entity sınıfları
│ └─ usecases/ # İş kuralları (veri işleme, filtreleme)
│
├─ presentation/ # UI katmanı
│ ├─ blocs/ / cubits/ # State management (Bloc, Riverpod, Provider)
│ ├─ pages/ # Ekranlar
│ └─ widgets/ # UI bileşenleri
│
└─ core/ # Global yardımcılar
├─ network/ # HTTP client, interceptors
├─ utils/ # Helper fonksiyonlar
└─ constants/ # Sabitler (URL, Keys)
🔹 Örnek API çağrısı (Repository Katmanı)
class UserRepository {
final ApiClient apiClient;
UserRepository(this.apiClient);
Future<User> getUser(int id) async {
final response = await apiClient.get('/users/$id/');
return User.fromJson(response.data);
}
}
🔹 Bloc / Cubit ile state yönetimi (Presentation)
class UserCubit extends Cubit<UserState> {
final UserRepository repository;
UserCubit(this.repository) : super(UserInitial());
Future<void> fetchUser(int id) async {
emit(UserLoading());
try {
final user = await repository.getUser(id);
emit(UserLoaded(user));
} catch (e) {
emit(UserError('Kullanıcı yüklenemedi'));
}
}
}
🔹 Avantajları
Test edilebilir: Domain ve Data katmanları bağımsız test edilebilir.
Esnek: API değişse bile UI ve iş mantığı minimal etkilenir.
Modüler: Farklı projelerde katmanları tekrar kullanabilirsin.
Yorumlar
Yorum Gönder