Uçtan Uca Zekat Hesaplama ve Takip Sistemi: Django ve Flutter Entegrasyonu
Hem web hem de mobil platformların birbiriyle nasıl konuştuğunu, veri tabanı işlemlerinin (CRUD) uçtan uca nasıl yönetildiğini özellikle bir bilgisayar laboratuvarı ortamında öğrencilere veya diğer geliştiricilere göstermek için kusursuz bir mimari.
Django'nun güçlü arka planı ve Flutter'ın esnek ön yüzü birleştiğinde ortaya çok verimli bir ekosistem çıkıyor. Bu eğitim makalesinde, temel %2.5 (1/40) zekat oranını baz alarak, hem web arayüzünden hem de mobil uygulamadan yönetilebilen bir "Zekat Hesaplama ve Takip Sistemi" kuracağız.
Kullanıcıların varlıklarını girip zekat miktarlarını hesaplayabildikleri, bu kayıtları listeleyip, güncelleyip, silebildikleri (CRUD) tam teşekküllü bir sistem inşa edeceğiz.
Bölüm 1: Django ile Arka Plan (Backend) ve Web Arayüzü
Django, hem standart web sayfalarını (HTML/CSS) sunmak hem de Flutter'ın haberleşeceği RESTful API'yi oluşturmak için merkez üssümüz olacak.
1. Kurulum ve Model Tasarımı
Öncelikle projemizi ve uygulamamızı oluşturalım. REST API oluşturmak için djangorestframework paketine ihtiyacımız var.
pip install django djangorestframework django-cors-headers
django-admin startproject zekat_projesi
cd zekat_projesi
python manage.py startapp hesaplayici
hesaplayici/models.py dosyasında veri tabanı modelimizi oluşturalım. Hesaplama mantığını modelin save metoduna ekleyerek işi otomatize edebiliriz:
from django.db import models
class ZekatKaydi(models.Model):
kullanici_adi = models.CharField(max_length=100, verbose_name="İsim Soyisim")
toplam_varlik = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="Toplam Varlık (TL)")
hesaplanan_zekat = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True)
kayit_tarihi = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
# 40'ta 1 (%2.5) oranında zekat hesaplama mantığı
if self.toplam_varlik:
self.hesaplanan_zekat = float(self.toplam_varlik) * 0.025
super().save(*args, **kwargs)
def __str__(self):
return f"{self.kullanici_adi} - {self.hesaplanan_zekat} TL"
2. Django Web Arayüzü (Web CRUD)
Web tarafı için standart Django formları ve görünümleri (Class-Based Views) kullanabilirsiniz.
hesaplayici/views.py içerisine standart web görünümlerini ekleyelim:
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from .models import ZekatKaydi
class ZekatListesi(ListView):
model = ZekatKaydi
template_name = 'hesaplayici/liste.html' # Bootstrap ile süsleyebilirsiniz
class ZekatEkle(CreateView):
model = ZekatKaydi
fields = ['kullanici_adi', 'toplam_varlik']
success_url = reverse_lazy('zekat_listesi')
# UpdateView ve DeleteView da benzer şekilde tanımlanır.
3. Flutter İçin REST API (API CRUD)
Flutter uygulamasının veri okuyup yazabilmesi için verilerimizi JSON formatına çevirmemiz gerekiyor.
hesaplayici/serializers.py dosyasını oluşturun:
from rest_framework import serializers
from .models import ZekatKaydi
class ZekatKaydiSerializer(serializers.ModelSerializer):
class Meta:
model = ZekatKaydi
fields = '__all__'
Şimdi API uç noktalarını (Endpoints) hesaplayici/api_views.py içinde oluşturalım:
from rest_framework import viewsets
from .models import ZekatKaydi
from .serializers import ZekatKaydiSerializer
class ZekatViewSet(viewsets.ModelViewSet):
queryset = ZekatKaydi.objects.all().order_by('-kayit_tarihi')
serializer_class = ZekatKaydiSerializer
Projenin urls.py dosyasında router ayarlarını yaparak API'yi dışa açın:
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from hesaplayici.api_views import ZekatViewSet
router = DefaultRouter()
router.register(r'zekat', ZekatViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)), # Flutter buradan bağlanacak
# Web View URL'leri buraya eklenebilir
]
Not: Local ağda (örneğin 15 bilgisayarlık bir laboratuvar ağında) test yaparken Django'yu python manage.py runserver 0.0.0.0:8000 komutuyla başlatmayı ve settings.py içinde ALLOWED_HOSTS = ['*'] ile CORS_ALLOW_ALL_ORIGINS = True ayarlarını yapmayı unutmayın.
Bölüm 2: Flutter ile Mobil Arayüz
Mobil tarafta, oluşturduğumuz bu API'ye HTTP istekleri (GET, POST, PUT, DELETE) atarak CRUD işlemlerini gerçekleştireceğiz.
1. Kurulum ve Model
pubspec.yaml dosyasına http paketini ekleyin:
dependencies:
flutter:
sdk: flutter
http: ^1.1.0
Gelen JSON verisini karşılayacak Dart modelimizi oluşturalım (zekat_model.dart):
class ZekatKaydi {
final int? id;
final String kullaniciAdi;
final double toplamVarlik;
final double? hesaplananZekat;
ZekatKaydi({this.id, required this.kullaniciAdi, required this.toplamVarlik, this.hesaplananZekat});
factory ZekatKaydi.fromJson(Map<String, dynamic> json) {
return ZekatKaydi(
id: json['id'],
kullaniciAdi: json['kullanici_adi'],
toplamVarlik: double.parse(json['toplam_varlik'].toString()),
hesaplananZekat: json['hesaplanan_zekat'] != null ? double.parse(json['hesaplanan_zekat'].toString()) : null,
);
}
}
2. API Servis Sınıfı (CRUD İşlemleri)
Django sunucumuzla konuşacak olan ağ katmanını yazalım (api_service.dart). Sunucu IP adresini, Django'yu çalıştırdığınız makinenin yerel IP'si (örn: 192.168.1.50) olarak ayarlamalısınız.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'zekat_model.dart';
class ApiService {
// Makinenizin veya sunucunuzun IP adresi
static const String baseUrl = 'http://192.168.1.X:8000/api/zekat/';
// READ (Listeleme)
Future<List<ZekatKaydi>> getKayitlar() async {
final response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
List jsonResponse = json.decode(utf8.decode(response.bodyBytes));
return jsonResponse.map((data) => ZekatKaydi.fromJson(data)).toList();
} else {
throw Exception('Veriler yüklenemedi');
}
}
// CREATE (Ekleme)
Future<void> addKayit(String isim, double varlik) async {
await http.post(
Uri.parse(baseUrl),
headers: <String, String>{'Content-Type': 'application/json; charset=UTF-8'},
body: jsonEncode(<String, dynamic>{
'kullanici_adi': isim,
'toplam_varlik': varlik,
}),
);
}
// DELETE (Silme)
Future<void> deleteKayit(int id) async {
await http.delete(Uri.parse('$baseUrl$id/'));
}
}
3. Kullanıcı Arayüzü (UI)
Uygulamanın ana ekranında kayıtları listeleyebilir ve yeni kayıt eklemek için bir Floating Action Button kullanabiliriz. (Kodu sade tutmak adına temel liste yapısı aşağıdadır):
import 'package:flutter/material.dart';
import 'api_service.dart';
import 'zekat_model.dart';
class AnaEkran extends StatefulWidget {
@override
_AnaEkranState createState() => _AnaEkranState();
}
class _AnaEkranState extends State<AnaEkran> {
final ApiService api = ApiService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Zekat Takip Sistemi')),
body: FutureBuilder<List<ZekatKaydi>>(
future: api.getKayitlar(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
var kayit = snapshot.data![index];
return ListTile(
title: Text(kayit.kullaniciAdi),
subtitle: Text('Varlık: ${kayit.toplamVarlik} ₺ - Zekat: ${kayit.hesaplananZekat} ₺'),
trailing: IconButton(
icon: Icon(Icons.delete, color: Colors.red),
onPressed: () async {
await api.deleteKayit(kayit.id!);
setState(() {}); // Ekranı yenile
},
),
);
},
);
} else if (snapshot.hasError) {
return Center(child: Text("${snapshot.error}"));
}
return Center(child: CircularProgressIndicator());
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Burada AlertDialog veya yeni sayfa açılarak API.addKayit çağrılır
},
child: Icon(Icons.add),
),
);
}
}
Sonuç
Bu mimariyle, veri bütünlüğünü Django'nun güvenli kollarında tutarken, Flutter ile akıcı bir mobil deneyim sağladık. Zekat miktarının backend (models.py) tarafında hesaplanması, hem web arayüzünden (Django Views) hem de mobil uygulamadan (Flutter HTTP POST) girilen verilerin her zaman aynı iş kurallarına tabi tutulmasını garanti eder. Bu yaklaşım, modern sistem tasarımının temel taşlarındandır ve öğrencilere web-mobil entegrasyonunu anlatmak için harika bir örnektir.
Projeyi doğrudan ayağa kaldırıp laboratuvarda veya kendi bilgisayarında test edebilmen için gereken dosyaların tam ve çalışır haldeki kodları:
Bölüm 1: Django (Backend & Web) Tam Kodları
Terminalde django-admin startproject zekat_projesi ve python manage.py startapp hesaplayici komutlarını çalıştırdıktan sonra dosyaları aşağıdaki gibi düzenleyebilirsin.
1. hesaplayici/models.py (Veri Tabanı ve Hesaplama Mantığı)
from django.db import models
class ZekatKaydi(models.Model):
kullanici_adi = models.CharField(max_length=100, verbose_name="İsim Soyisim")
toplam_varlik = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="Toplam Varlık (TL)")
hesaplanan_zekat = models.DecimalField(max_digits=15, decimal_places=2, blank=True, null=True, verbose_name="Hesaplanan Zekat")
kayit_tarihi = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
# Toplam varlığın 1/40'ı (%2.5) hesaplanır
if self.toplam_varlik:
self.hesaplanan_zekat = float(self.toplam_varlik) * 0.025
super().save(*args, **kwargs)
def __str__(self):
return f"{self.kullanici_adi} - {self.hesaplanan_zekat} TL"
2. hesaplayici/serializers.py (JSON Dönüştürücü)
from rest_framework import serializers
from .models import ZekatKaydi
class ZekatKaydiSerializer(serializers.ModelSerializer):
class Meta:
model = ZekatKaydi
fields = ['id', 'kullanici_adi', 'toplam_varlik', 'hesaplanan_zekat', 'kayit_tarihi']
3. hesaplayici/api_views.py (Flutter için REST API Görünümleri)
from rest_framework import viewsets
from .models import ZekatKaydi
from .serializers import ZekatKaydiSerializer
class ZekatViewSet(viewsets.ModelViewSet):
queryset = ZekatKaydi.objects.all().order_by('-kayit_tarihi')
serializer_class = ZekatKaydiSerializer
4. hesaplayici/views.py (Web Arayüzü için Görünümler)
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, DeleteView
from .models import ZekatKaydi
class ZekatListesi(ListView):
model = ZekatKaydi
template_name = 'hesaplayici/liste.html'
context_object_name = 'kayitlar'
ordering = ['-kayit_tarihi']
class ZekatEkle(CreateView):
model = ZekatKaydi
fields = ['kullanici_adi', 'toplam_varlik']
template_name = 'hesaplayici/form.html'
success_url = reverse_lazy('zekat_listesi')
class ZekatSil(DeleteView):
model = ZekatKaydi
template_name = 'hesaplayici/sil_onay.html'
success_url = reverse_lazy('zekat_listesi')
5. zekat_projesi/urls.py (Ana URL Yönlendirmeleri)
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from hesaplayici.api_views import ZekatViewSet
from hesaplayici import views
# API Router ayarları
router = DefaultRouter()
router.register(r'zekat', ZekatViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
# Flutter'ın istek atacağı API endpoint'i:
path('api/', include(router.urls)),
# Web arayüzü URL'leri:
path('', views.ZekatListesi.as_view(), name='zekat_listesi'),
path('ekle/', views.ZekatEkle.as_view(), name='zekat_ekle'),
path('sil/<int:pk>/', views.ZekatSil.as_view(), name='zekat_sil'),
]
(Not: settings.py içinde INSTALLED_APPS listesine 'rest_framework', 'corsheaders' ve 'hesaplayici' uygulamalarını eklemeyi ve CORS ayarlarını yapmayı unutma.)
Bölüm 2: Flutter (Mobil Uygulama) Tam Kodları
Aşağıdaki kodları Flutter projenin lib klasörü altında ilgili dosyaları oluşturarak yapıştırabilirsin.
1. lib/zekat_model.dart (Veri Modeli)
class ZekatKaydi {
final int? id;
final String kullaniciAdi;
final double toplamVarlik;
final double? hesaplananZekat;
ZekatKaydi({
this.id,
required this.kullaniciAdi,
required this.toplamVarlik,
this.hesaplananZekat,
});
factory ZekatKaydi.fromJson(Map<String, dynamic> json) {
return ZekatKaydi(
id: json['id'],
kullaniciAdi: json['kullanici_adi'],
toplamVarlik: double.parse(json['toplam_varlik'].toString()),
hesaplananZekat: json['hesaplanan_zekat'] != null
? double.parse(json['hesaplanan_zekat'].toString())
: null,
);
}
}
2. lib/api_service.dart (Django ile Haberleşme Servisi)
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'zekat_model.dart';
class ApiService {
// Django sunucusunun çalıştığı makinenin IP adresi (Pardus makinenin IP'si vb.)
// Emülatör kullanıyorsan 10.0.2.2 olabilir. Gerçek cihazda aynı Wi-Fi'daki yerel IP'yi yazmalısın.
static const String baseUrl = 'http://192.168.1.100:8000/api/zekat/';
Future<List<ZekatKaydi>> getKayitlar() async {
final response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
// Türkçe karakter sorunu yaşamamak için utf8.decode kullanıyoruz
List jsonResponse = json.decode(utf8.decode(response.bodyBytes));
return jsonResponse.map((data) => ZekatKaydi.fromJson(data)).toList();
} else {
throw Exception('Kayıtlar yüklenemedi: ${response.statusCode}');
}
}
Future<void> addKayit(String isim, double varlik) async {
final response = await http.post(
Uri.parse(baseUrl),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, dynamic>{
'kullanici_adi': isim,
'toplam_varlik': varlik,
}),
);
if (response.statusCode != 201) {
throw Exception('Kayıt eklenemedi');
}
}
Future<void> deleteKayit(int id) async {
final response = await http.delete(Uri.parse('$baseUrl$id/'));
if (response.statusCode != 204) {
throw Exception('Kayıt silinemedi');
}
}
}
3. lib/main.dart (Tam ve Çalışır Kullanıcı Arayüzü)
import 'package:flutter/material.dart';
import 'api_service.dart';
import 'zekat_model.dart';
void main() {
runApp(const ZekatUygulamasi());
}
class ZekatUygulamasi extends StatelessWidget {
const ZekatUygulamasi({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Zekat Hesaplayıcı',
theme: ThemeData(primarySwatch: Colors.green),
home: const AnaEkran(),
debugShowCheckedModeBanner: false,
);
}
}
class AnaEkran extends StatefulWidget {
const AnaEkran({Key? key}) : super(key: key);
@override
_AnaEkranState createState() => _AnaEkranState();
}
class _AnaEkranState extends State<AnaEkran> {
final ApiService apiService = ApiService();
late Future<List<ZekatKaydi>> kayitlar;
@override
void initState() {
super.initState();
verileriYenile();
}
void verileriYenile() {
setState(() {
kayitlar = apiService.getKayitlar();
});
}
// Yeni Kayıt Ekleme Penceresi (Dialog)
void _kayitEkleDialogGoster() {
final isimController = TextEditingController();
final varlikController = TextEditingController();
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Yeni Zekat Kaydı Ekle'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: isimController,
decoration: const InputDecoration(labelText: 'İsim Soyisim'),
),
TextField(
controller: varlikController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(labelText: 'Toplam Varlık (TL)'),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('İptal'),
),
ElevatedButton(
onPressed: () async {
if (isimController.text.isNotEmpty && varlikController.text.isNotEmpty) {
double varlik = double.parse(varlikController.text);
await apiService.addKayit(isimController.text, varlik);
Navigator.pop(context);
verileriYenile(); // Listeyi güncelle
}
},
child: const Text('Kaydet'),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Zekat Kayıtları (Flutter & Django)'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: verileriYenile,
)
],
),
body: FutureBuilder<List<ZekatKaydi>>(
future: kayitlar,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Hata oluştu: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(child: Text('Henüz kayıt bulunmuyor.'));
}
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final kayit = snapshot.data![index];
return Card(
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: ListTile(
title: Text(
kayit.kullaniciAdi,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
'Varlık: ${kayit.toplamVarlik.toStringAsFixed(2)} ₺\nZekat: ${kayit.hesaplananZekat?.toStringAsFixed(2)} ₺',
),
isThreeLine: true,
trailing: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () async {
await apiService.deleteKayit(kayit.id!);
verileriYenile();
},
),
),
);
},
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: _kayitEkleDialogGoster,
child: const Icon(Icons.add),
),
);
}
}
Django'da views.py dosyasında çağırdığımız (liste.html, form.html, sil_onay.html) HTML şablon dosyalarını vermeyi atlamışım.
Bu dosyaları Django projenin içinde, hesaplayici uygulamasının altında şu klasör yapısını oluşturarak içine kaydetmelisin:
hesaplayici/templates/hesaplayici/
Tasarımların düzgün görünmesi için temel bir Bootstrap 5 yapısı kullandım.
1. base.html (Ana Şablon)
Tüm sayfalarda tekrar eden menü ve kütüphane kodlarını tek bir yerde tutmak için bir ana şablon oluşturalım.
Dosya Yolu: hesaplayici/templates/hesaplayici/base.html
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zekat Takip Sistemi</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
<nav class="navbar navbar-expand-lg navbar-dark bg-success mb-4">
<div class="container">
<a class="navbar-brand" href="{% url 'zekat_listesi' %}">Zekat Takip (Django Web)</a>
</div>
</nav>
<div class="container">
{% block content %}
{% endblock %}
</div>
</body>
</html>
2. liste.html (Kayıtların Listelendiği Ana Sayfa)
Bu sayfa veri tabanındaki zekat kayıtlarını bir tablo halinde gösterir.
Dosya Yolu: hesaplayici/templates/hesaplayici/liste.html
{% extends 'hesaplayici/base.html' %}
{% block content %}
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h4 class="mb-0">Zekat Kayıtları</h4>
<a href="{% url 'zekat_ekle' %}" class="btn btn-success">Yeni Kayıt Ekle</a>
</div>
<div class="card-body">
{% if kayitlar %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>İsim Soyisim</th>
<th>Toplam Varlık (TL)</th>
<th>Hesaplanan Zekat (TL)</th>
<th>Tarih</th>
<th>İşlemler</th>
</tr>
</thead>
<tbody>
{% for kayit in kayitlar %}
<tr>
<td>{{ kayit.kullanici_adi }}</td>
<td>{{ kayit.toplam_varlik }} ₺</td>
<td><strong>{{ kayit.hesaplanan_zekat }} ₺</strong></td>
<td>{{ kayit.kayit_tarihi|date:"d.m.Y H:i" }}</td>
<td>
<a href="{% url 'zekat_sil' kayit.pk %}" class="btn btn-sm btn-danger">Sil</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="alert alert-info">Henüz sisteme eklenmiş bir kayıt bulunmuyor.</div>
{% endif %}
</div>
</div>
{% endblock %}
3. form.html (Yeni Kayıt Ekleme Sayfası)
Kullanıcıdan isim ve toplam varlık bilgisini aldığımız form sayfasıdır.
Dosya Yolu: hesaplayici/templates/hesaplayici/form.html
{% extends 'hesaplayici/base.html' %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h4 class="mb-0">Yeni Zekat Kaydı Ekle</h4>
</div>
<div class="card-body">
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="d-grid gap-2 mt-4">
<button type="submit" class="btn btn-success">Kaydet ve Hesapla</button>
<a href="{% url 'zekat_listesi' %}" class="btn btn-secondary">İptal</a>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
4. sil_onay.html (Kayıt Silme Onay Sayfası)
Yanlışlıkla silmeleri önlemek için kullanıcıya "Emin misiniz?" diye sorduğumuz sayfa.
Dosya Yolu: hesaplayici/templates/hesaplayici/sil_onay.html
{% extends 'hesaplayici/base.html' %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card shadow-sm border-danger">
<div class="card-header bg-danger text-white">
<h4 class="mb-0">Kayıt Silme Onayı</h4>
</div>
<div class="card-body text-center">
<p class="lead"><strong>{{ object.kullanici_adi }}</strong> isimli kişiye ait zekat kaydını silmek istediğinize emin misiniz?</p>
<p class="text-muted">Bu işlem geri alınamaz.</p>
<form method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-danger px-4">Evet, Sil</button>
<a href="{% url 'zekat_listesi' %}" class="btn btn-secondary px-4">İptal</a>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
Bu dosyaları ekledikten sonra, web tarayıcından http://127.0.0.1:8000/ adresine (veya belirlediğin IP'ye) girdiğinde güzel görünümlü bir web arayüzü ile karşılaşacaksın. Buradan eklediğin veriler anında Flutter mobil uygulamana da yansıyacaktır.
zekat_projesi/settings.py dosyasını açıp aşağıdaki ilgili bölümleri güncelleyebilirsin:
1. INSTALLED_APPS (Kurulu Uygulamalar)
Kendi oluşturduğumuz hesaplayici uygulamasını, rest_framework'ü ve dışarıdan gelen API isteklerini kabul etmek için corsheaders'ı bu listeye eklemelisin.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Kendi uygulamamız ve kurduğumuz kütüphaneler:
'hesaplayici',
'rest_framework',
'corsheaders',
]
2. MIDDLEWARE (Ara Katmanlar)
CORS middleware'ini listeye eklemen gerekiyor. Bunun CommonMiddleware'in üzerinde olması son derece önemlidir.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# CORS Middleware buraya eklenmeli:
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
3. ALLOWED_HOSTS ve CORS İzinleri
Geliştirme aşamasında API'nin her IP'den (özellikle telefonundan veya emülatörden) gelen isteklere yanıt verebilmesi için ALLOWED_HOSTS ayarını güncellemelisin. Ayrıca dosyanın en altına CORS izin kodunu eklemelisin.
# Dosyanın üst kısımlarındaki bu ayarı bulup '*' yapın:
ALLOWED_HOSTS = ['*']
# ----- DOSYANIN EN ALTINA EKLEYEBİLİRSİNİZ -----
# REST Framework varsayılan ayarları (İsteğe bağlı ama iyi bir standarttır)
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
# Flutter mobil uygulamasından gelecek isteklere izin verir
CORS_ALLOW_ALL_ORIGINS = True
Bu ayarları kaydettikten sonra sırasıyla şu komutları çalıştırarak projeyi hazır hale getirebilirsin:
python manage.py makemigrationspython manage.py migratepython manage.py runserver 0.0.0.0:8000(Bu şekilde başlatırsan yerel ağındaki diğer cihazlar da bu sunucuya bağlanabilir).
Yorumlar
Yorum Gönder