Takip et

Temel Kavramlar: Neden Django ve React Birlikte Harika Bir İkili?

Django ve React ile Etkileşimli To-Do Uygulaması Nasıl Geliştirilir?

Modern web geliştirme dünyasında, kullanıcı beklentileri her geçen gün artıyor. Dinamik, hızlı ve etkileşimli uygulamalar oluşturmak için doğru teknoloji kombinasyonunu seçmek kritik önem taşıyor. Peki, hem sağlam bir arka plan (backend) hem de zengin bir kullanıcı arayüzü (frontend) sunan bir To-Do uygulaması geliştirmek mümkün mü? Bu makalede, Python tabanlı güçlü Django framework’ünü ve JavaScript’in popüler kütüphanesi React’ı bir araya getirerek, sıfırdan modern bir To-Do uygulaması nasıl inşa edeceğinizi adım adım keşfedeceğiz. Bu rehber, hem yeni başlayanlar hem de deneyimli geliştiriciler için değerli bilgiler sunacak, böylece projelerinizi bir üst seviyeye taşıyabileceksiniz.

Temel Kavramlar: Neden Django ve React Birlikte Harika Bir İkili?

Web uygulaması geliştirirken, genellikle iki ana bileşene odaklanırız: verilerin yönetildiği ve iş mantığının yürütüldüğü arka plan (backend) ile kullanıcıların etkileşimde bulunduğu ön yüz (frontend). Bu iki katmanın doğru bir şekilde entegre edilmesi, uygulamanın performansı, ölçeklenebilirliği ve genel kullanıcı deneyimi için hayati öneme sahiptir. İşte bu noktada Django ve React ikilisi devreye giriyor. Django, sağlam bir API oluşturmak için gerekli tüm araçları sunarken, React bu API’yi kullanarak dinamik ve hızlı bir kullanıcı arayüzü inşa etmemizi sağlıyor. Bu ayrım, her bir katmanın kendi uzmanlık alanına odaklanmasına olanak tanıyarak geliştirme sürecini daha verimli hale getiriyor.

Django Nedir ve Backend Geliştirmede Neden Tercih Edilmeli?

Django, “web geliştiricileri için mükemmeliyetçi bir framework” sloganıyla bilinen, Python tabanlı, yüksek seviyeli bir web framework’üdür. Hızlı geliştirme ve “DRY” (Don’t Repeat Yourself – Kendini Tekrar Etme) prensibini benimser. Django’nun en büyük avantajlarından biri, birçok temel web geliştirme ihtiyacını (kullanıcı kimlik doğrulama, yönetim paneli, veritabanı ORM’i vb.) “pil dahil” (batteries-included) bir yaklaşımla sunmasıdır. Bu, geliştiricilerin sıfırdan her şeyi yazmak yerine, projenin özgün mantığına odaklanmasına olanak tanır. Özellikle API geliştirme söz konusu olduğunda, Django REST Framework (DRF) gibi güçlü eklentiler sayesinde, dakikalar içinde RESTful API’ler oluşturmak mümkündür. DRF, serileştirme, kimlik doğrulama, yetkilendirme ve viewset’ler gibi özellikleriyle API geliştirme sürecini oldukça basitleştirir. Güvenlik konusunda da Django, SQL enjeksiyonu, XSS ve CSRF gibi yaygın web saldırılarına karşı yerleşik korumalar sunarak geliştiricilere büyük bir yükü hafifletir. Bu sayede, backend tarafında sağlam, güvenli ve ölçeklenebilir bir yapı kurmak çok daha kolay hale gelir.

React Nedir ve Kullanıcı Deneyimine Nasıl Katkı Sağlar?

React, Facebook tarafından geliştirilen, kullanıcı arayüzleri oluşturmak için kullanılan bir JavaScript kütüphanesidir. Bileşen tabanlı yapısıyla öne çıkar; bu, uygulamanın küçük, bağımsız ve yeniden kullanılabilir parçalara (component’lere) ayrılmasını sağlar. Bu yaklaşım, karmaşık UI’ları yönetmeyi ve geliştirmeyi oldukça kolaylaştırır. React’ın en önemli özelliklerinden biri Virtual DOM (Sanal DOM) kullanmasıdır. Geleneksel olarak, bir web sayfasında değişiklik olduğunda tarayıcı tüm DOM’u yeniden çizmek zorunda kalır, bu da performans sorunlarına yol açabilir. Virtual DOM ise, önce değişiklikleri sanal ortamda hesaplar ve sadece gerekli olan kısımları gerçek DOM’a yansıtır. Bu optimizasyon, özellikle yoğun veri akışı olan ve sık güncellenen uygulamalarda inanılmaz bir hız ve akıcılık sağlar. Tek sayfa uygulamaları (SPA) geliştirmek için ideal olan React, kullanıcıların sayfalar arasında geçiş yaparken tam bir sayfa yenilemesi yaşamamasını sağlar, bu da daha akıcı ve masaüstü uygulaması benzeri bir deneyim sunar. Kullanıcı arayüzünün dinamikliği ve etkileşimliliği, React’ın sunduğu en büyük avantajlardandır.

Frontend ve Backend Ayrımı Neden Önemli?

Frontend ve backend’in ayrı katmanlar olarak geliştirilmesi, modern yazılım mimarisinin temel taşlarından biridir. Bu “decoupled” veya “ayrık” mimari, birçok avantaj sunar. İlk olarak, ölçeklenebilirlik açısından önemlidir. Her iki katman da birbirinden bağımsız olarak ölçeklendirilebilir; örneğin, backend’iniz çok fazla API isteği alırken, frontend’iniz aynı oranda trafik görmeyebilir veya tam tersi. İkinci olarak, farklı ekiplerin aynı proje üzerinde eş zamanlı ve bağımsız çalışmasına olanak tanır. Frontend ekibi kullanıcı arayüzüne odaklanırken, backend ekibi veri modelleri ve API mantığı üzerinde çalışabilir. Bu, geliştirme hızını artırır ve ekip içi koordinasyonu kolaylaştırır. Üçüncü olarak, bu ayrım farklı platformlara destek vermeyi kolaylaştırır. Aynı backend API’si, hem web tabanlı bir React uygulaması hem de mobil (React Native ile) veya masaüstü uygulamaları tarafından kullanılabilir. Bu da kod tekrarını azaltır ve tutarlı bir veri erişimi sağlar. Son olarak, teknolojileri bağımsız olarak güncelleme ve değiştirme esnekliği sunar. Örneğin, gelecekte React yerine başka bir frontend kütüphanesine geçiş yapmak isterseniz, backend’iniz bu değişiklikten etkilenmez. Bu esneklik, uzun vadeli projeler için kritik bir avantajdır.

Proje Ortamını Kurma: Gelişime Hazırlık Adımları Nelerdir?

Başarılı bir uygulama geliştirmek için sağlam bir temel atmak şarttır. Bu temel, doğru geliştirme ortamını kurmaktan geçer. Django ve React projelerimizi ayrı ayrı yönetmek, hem bağımlılık çakışmalarını önleyecek hem de her bir katmanın kendi ekosisteminde sorunsuz çalışmasını sağlayacaktır. Bu bölümde, gerekli araçların kurulumundan başlayarak, Django backend’i ve React frontend’i için ilk adımları nasıl atacağınızı detaylı bir şekilde ele alacağız. Doğru yapılandırma, ilerleyen adımlarda karşınıza çıkabilecek birçok potansiyel sorunu önleyecektir.

Gerekli Araçlar: Neler Yüklemeliyiz?

Bu projeye başlamadan önce bilgisayarınızda kurulu olması gereken temel araçlar şunlardır:

  • Python 3.x: Django’nun çalışması için gereklidir. python.org adresinden indirilebilir.
  • pip: Python paket yöneticisi. Python ile birlikte gelir.
  • Node.js ve npm (veya yarn): React uygulamaları için JavaScript çalışma zamanı ve paket yöneticisi. nodejs.org adresinden indirilebilir.
  • virtualenv (veya venv): Python projeleri için izole edilmiş sanal ortamlar oluşturmak amacıyla kullanılır. Bağımlılık çakışmalarını önler.

Bu araçların kurulumunu tamamladıktan sonra, projemizin temel dizin yapısını oluşturalım. Genellikle, ana dizinde hem backend hem de frontend projelerini barındırırız:


    todo-app/
    ├── todo-backend/
    └── todo-frontend/
    

Django Backend Kurulumu ve İlk Adımlar

Şimdi sıra backend projemizi kurmaya geldi. İlk olarak, todo-backend dizinine gidelim ve bir sanal ortam oluşturalım:


    cd todo-backend
    python -m venv venv
    source venv/bin/activate  # Linux/macOS
    # venv\Scripts\activate   # Windows
    

Sanal ortamı etkinleştirdikten sonra, Django ve Django REST Framework’ü kuralım:


    pip install django djangorestframework django-cors-headers
    

Ardından, Django projemizi ve bir uygulama (app) oluşturalım:


    django-admin startproject todo_backend .
    python manage.py startapp api
    

Proje yapımız aşağıdaki gibi görünecektir:


    todo-backend/
    ├── venv/
    ├── todo_backend/
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── api/
    │   ├── migrations/
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py
    

Şimdi todo_backend/settings.py dosyasını açarak gerekli yapılandırmaları yapalım. INSTALLED_APPS listesine 'rest_framework', 'corsheaders' ve 'api' uygulamalarımızı eklemeliyiz:


    # todo_backend/settings.py

    INSTALLED_APPS = [
        # ... diğer Django uygulamaları ...
        'rest_framework',
        'corsheaders',
        'api', # Kendi api uygulamamız
    ]

    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware', # CORS middleware'ı en üste ekleyin
        # ... diğer middleware'ler ...
    ]

    CORS_ALLOW_ALL_ORIGINS = True # Geliştirme ortamı için tüm origin'lere izin veriyoruz.
                                 # Üretim ortamında belirli origin'leri belirtmelisiniz.
    

Uzman İpucu: Üretim ortamında CORS_ALLOW_ALL_ORIGINS = True kullanmak güvenlik açığı oluşturur. Bunun yerine, CORS_ALLOWED_ORIGINS listesini kullanarak sadece frontend uygulamanızın URL’sini belirtmelisiniz. Örneğin: CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]

Veritabanı tablolarını oluşturalım:


    python manage.py makemigrations
    python manage.py migrate
    

Backend sunucumuzu çalıştırarak her şeyin yolunda olup olmadığını kontrol edebiliriz:


    python manage.py runserver
    

Tarayıcınızda http://127.0.0.1:8000/ adresine giderek Django’nun varsayılan karşılama sayfasını görmelisiniz.

React Frontend Kurulumu ve İlk Adımlar

Frontend tarafında ise, todo-frontend dizinine geçerek React projemizi oluşturalım:


    cd ../todo-frontend
    npx create-react-app .
    

npx create-react-app . komutu, mevcut dizine React projesi dosyalarını kurar. Kurulum tamamlandıktan sonra, API istekleri yapmak için axios kütüphanesini kuralım:


    npm install axios
    # veya
    yarn add axios
    

Frontend sunucumuzu başlatmak için:


    npm start
    # veya
    yarn start
    

Tarayıcınızda http://localhost:3000/ adresine giderek React’ın varsayılan karşılama sayfasını görmelisiniz. Artık hem Django backend’imiz hem de React frontend’imiz çalışmaya hazır. Bir sonraki adımda, Django REST Framework ile API’mizi geliştirmeye başlayacağız.

Django REST Framework ile API Geliştirme: Görevleri Nasıl Yönetiriz?

Uygulamamızın kalbi, görevleri (To-Do öğelerini) yönetebileceğimiz bir API olacaktır. Bu API, görevlerin oluşturulması, okunması, güncellenmesi ve silinmesi (CRUD işlemleri) gibi temel işlevleri yerine getirecektir. Django REST Framework (DRF), bu süreci oldukça kolaylaştıran güçlü araçlar sunar. Model tanımından başlayarak, verileri JSON formatına dönüştüren serializer’lara ve son olarak API uç noktalarını oluşturan viewset’lere kadar her adımı detaylıca inceleyeceğiz. Bu bölümde, frontend’in ihtiyaç duyacağı tüm veri etkileşimlerini sağlayacak sağlam bir backend altyapısı kuracağız.

Model Oluşturma: Görev Verilerini Nasıl Tutarız?

İlk olarak, api/models.py dosyasını açarak To-Do öğelerimiz için bir model tanımlayalım. Bu model, her bir görevin hangi özelliklere sahip olacağını belirleyecektir:


    # api/models.py

    from django.db import models

    class Todo(models.Model):
        title = models.CharField(max_length=120)
        description = models.TextField()
        completed = models.BooleanField(default=False)
        created_at = models.DateTimeField(auto_now_add=True)

        def _str_(self):
            return self.title
    

Bu model, her görevin bir başlığı (title), açıklaması (description), tamamlanıp tamamlanmadığını gösteren bir durumu (completed) ve oluşturulma zamanını (created_at) içerecektir. Modeli tanımladıktan sonra, veritabanı tablolarını oluşturmak için migrasyonları çalıştırmalıyız:


    python manage.py makemigrations api
    python manage.py migrate
    

Bu komutlar, Django’nun Todo modelimiz için gerekli veritabanı şemasını oluşturmasını sağlar. Artık veritabanımızda görevlerimizi saklayabileceğimiz bir yapı mevcut.

Serializer Yazma: Veri Dönüşümünü Nasıl Sağlarız?

Django modelleri Python nesneleridir ve doğrudan HTTP yanıtı olarak gönderilemezler. React gibi frontend uygulamalarının anlayabileceği JSON formatına dönüştürülmeleri gerekir. İşte bu noktada serializer’lar devreye girer. api uygulamamızın içinde yeni bir dosya olan api/serializers.py oluşturalım:


    # api/serializers.py

    from rest_framework import serializers
    from .models import Todo

    class TodoSerializer(serializers.ModelSerializer):
        class Meta:
            model = Todo
            fields = ('id', 'title', 'description', 'completed', 'created_at')
    

TodoSerializer sınıfı, Todo modelimizdeki alanları JSON formatına çevirecektir. ModelSerializer, Django modelinden otomatik olarak alanları ve doğrulayıcıları türetir, bu da bize büyük kolaylık sağlar. fields tuple’ı, API yanıtında hangi alanların gösterileceğini belirtir. id alanı, her görev için benzersiz bir tanımlayıcı görevi görecektir.

Viewset ve URL Yapılandırması: API Uç Noktalarını Nasıl Tanımlarız?

Şimdi sıra, API uç noktalarımızı oluşturmaya geldi. Django REST Framework, CRUD işlemlerini kapsayan viewset’ler sayesinde bu süreci oldukça basitleştirir. api/views.py dosyasını güncelleyelim:


    # api/views.py

    from rest_framework import viewsets
    from .serializers import TodoSerializer
    from .models import Todo

    class TodoViewSet(viewsets.ModelViewSet):
        queryset = Todo.objects.all().order_by('-created_at')
        serializer_class = TodoSerializer
    

TodoViewSet, Todo modeli için otomatik olarak list, retrieve, create, update, partial_update ve destroy gibi eylemleri sağlar. queryset, hangi verilerin çekileceğini, serializer_class ise bu verilerin nasıl serileştirileceğini belirtir. Burada, görevleri oluşturulma zamanına göre tersten sıralayarak en yenilerin üstte görünmesini sağlıyoruz.

Son olarak, bu viewset’i URL’lere bağlamamız gerekiyor. Django REST Framework’ün DefaultRouter‘ı, viewset’ler için otomatik olarak URL yapılandırması yapar, bu da bize zaman kazandırır. todo_backend/urls.py dosyasını güncelleyelim:


    # todo_backend/urls.py

    from django.contrib import admin
    from django.urls import path, include
    from rest_framework import routers
    from api import views

    router = routers.DefaultRouter()
    router.register(r'todos', views.TodoViewSet)

    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/', include(router.urls)), # API uç noktalarımızı ekledik
    ]
    

Artık backend sunucumuz çalışırken (python manage.py runserver), http://127.0.0.1:8000/api/todos/ adresine giderek DRF’nin otomatik olarak oluşturduğu API tarayıcısını görebilirsiniz. Buradan yeni görevler oluşturabilir, mevcutları listeleyebilir, güncelleyebilir ve silebilirsiniz. Bu, API’mizin doğru çalıştığını doğrulamak için harika bir yoldur. Postman veya Insomnia gibi araçlarla da bu uç noktaları test edebilirsiniz. Örneğin, yeni bir görev oluşturmak için POST isteğiyle aşağıdaki gibi bir JSON gönderebilirsiniz:


    {
        "title": "Alışveriş Yap",
        "description": "Marketten süt, ekmek ve yumurta al.",
        "completed": false
    }
    

Bu adımlarla, React frontend’imizin kullanabileceği tam işlevsel bir RESTful API’yi başarıyla kurmuş olduk. Backend tarafındaki bu sağlam yapı, frontend geliştirmemizi çok daha kolay hale getirecektir.

React ile Kullanıcı Arayüzü Oluşturma: Görevleri Dinamik Olarak Nasıl Görüntüleriz?

Backend API’miz hazır olduğuna göre, sıra kullanıcıların görevlerini görebileceği, ekleyebileceği, düzenleyebileceği ve silebileceği etkileşimli bir arayüz oluşturmaya geldi. React’ın component tabanlı yapısı ve state yönetimi, bu tür dinamik arayüzleri inşa etmek için mükemmel bir uyum sağlar. Bu bölümde, React uygulamasının temel component yapısını oluşturacak, backend API’mizle nasıl iletişim kuracağımızı öğrenecek ve kullanıcı girişlerini yönetmek için formları nasıl kullanacağımızı adım adım inceleyeceğiz. Amacımız, kullanıcı dostu ve akıcı bir To-Do deneyimi sunmaktır.

Component Yapısı: Uygulamayı Nasıl Bölümlere Ayırırız?

React’ta her şey bir component’tir. Uygulamamızı yönetilebilir parçalara ayırmak için aşağıdaki temel component’leri oluşturalım:

  • App.js: Ana component, tüm uygulamayı sarar.
  • TodoList.js: Görev listesini görüntüler.
  • TodoItem.js: Her bir görevi (başlık, açıklama, tamamlandı durumu) temsil eder.
  • TodoForm.js: Yeni görev eklemek veya mevcut görevleri düzenlemek için formu içerir.

src klasörünün altında components adında yeni bir klasör oluşturalım ve bu component dosyalarını içine yerleştirelim. Örneğin, src/components/TodoList.js gibi.

İlk olarak, src/App.js dosyamızı temizleyelim ve temel yapıyı kuralım:


    // src/App.js

    import React, { useState, useEffect } from 'react';
    import axios from 'axios';
    import TodoList from './components/TodoList';
    import TodoForm from './components/TodoForm';
    import './App.css'; // Stil dosyamızı da ekleyelim

    function App() {
        const [todos, setTodos] = useState([]);
        const [editingTodo, setEditingTodo] = useState(null); // Düzenlenen görevi tutmak için state

        // API'den görevleri çekme
        useEffect(() => {
            fetchTodos();
        }, []);

        const fetchTodos = async () => {
            try {
                const response = await axios.get('http://localhost:8000/api/todos/');
                setTodos(response.data);
            } catch (error) {
                console.error('Görevler çekilirken hata oluştu:', error);
            }
        };

        // ... Diğer CRUD fonksiyonları buraya gelecek ...

        return (
            

To-Do Uygulaması

setEditingTodo(null)} />
); } export default App;

Bu temel yapı, todos state’ini tutacak, API’den görevleri çekecek ve TodoList ile TodoForm component’lerini render edecektir. editingTodo state’i ise bir görevin düzenlenip düzenlenmediğini kontrol etmek için kullanılacak.

API Entegrasyonu: Backend ile Nasıl İletişim Kurarız?

axios kütüphanesi sayesinde backend API’mizle iletişim kurmak oldukça kolaydır. App.js içinde CRUD operasyonlarını gerçekleştiren fonksiyonları tanımlayalım:


    // src/App.js (devamı)

    // Yeni görev ekleme
    const addTodo = async (todo) => {
        try {
            const response = await axios.post('http://localhost:8000/api/todos/', todo);
            setTodos([response.data, ...todos]); // Yeni görevi listenin başına ekle
        } catch (error) {
            console.error('Görev eklenirken hata oluştu:', error);
        }
    };

    // Görev silme
    const deleteTodo = async (id) => {
        try {
            await axios.delete(http://localhost:8000/api/todos/${id}/);
            setTodos(todos.filter(todo => todo.id !== id));
        } catch (error) {
            console.error('Görev silinirken hata oluştu:', error);
        }
    };

    // Görevi düzenleme (state'i ayarlar)
    const handleEdit = (todo) => {
        setEditingTodo(todo);
    };

    // Görevi güncelleme
    const updateTodo = async (updatedTodo) => {
        try {
            const response = await axios.put(http://localhost:8000/api/todos/${updatedTodo.id}/, updatedTodo);
            setTodos(todos.map(todo => (todo.id === updatedTodo.id ? response.data : todo)));
            setEditingTodo(null); // Düzenleme modundan çık
        } catch (error) {
            console.error('Görev güncellenirken hata oluştu:', error);
        }
    };

    // Görev tamamlandı durumunu değiştirme
    const toggleComplete = async (id, completed) => {
        try {
            const todoToUpdate = todos.find(todo => todo.id === id);
            if (!todoToUpdate) return;

            const response = await axios.patch(http://localhost:8000/api/todos/${id}/, { completed: !completed });
            setTodos(todos.map(todo => (todo.id === id ? response.data : todo)));
        } catch (error) {
            console.error('Görev durumu güncellenirken hata oluştu:', error);
        }
    };
    

Bu fonksiyonlar, useState ve useEffect hook’larını kullanarak component’in yaşam döngüsünü ve durumunu yönetir. useEffect, component ilk yüklendiğinde görevleri çekmek için kullanılırken, diğer fonksiyonlar kullanıcı etkileşimleriyle tetiklenir ve API’ye istek gönderir.

Form Yönetimi ve State Güncelleme: Kullanıcı Girişlerini Nasıl İşleriz?

TodoForm.js component’i, yeni görev eklemek ve mevcut görevleri düzenlemek için kullanılacaktır. Bu form, title ve description alanlarını içerecek ve kullanıcının girişlerini yakalamak için useState hook’larını kullanacaktır.


    // src/components/TodoForm.js

    import React, { useState, useEffect } from 'react';
    import './TodoForm.css'; // Stil dosyası

    function TodoForm({ onSave, initialData, onCancelEdit }) {
        const [title, setTitle] = useState('');
        const [description, setDescription] = useState('');

        useEffect(() => {
            if (initialData) {
                setTitle(initialData.title);
                setDescription(initialData.description);
            } else {
                setTitle('');
                setDescription('');
            }
        }, [initialData]);

        const handleSubmit = (e) => {
            e.preventDefault();
            if (!title.trim()) return;
            onSave({ id: initialData?.id, title, description });
            setTitle('');
            setDescription('');
            onCancelEdit(); // Kayıt sonrası düzenleme modundan çık
        };

        return (
            
setTitle(e.target.value)} required /> {initialData && ( )}
); } export default TodoForm;

TodoList.js ve TodoItem.js component’leri de benzer şekilde props aracılığıyla görev verilerini alacak ve bunları ekranda gösterecektir. TodoItem içinde düzenleme ve silme butonları bulunacak, bu butonlara tıklandığında App.js‘teki ilgili fonksiyonlar çağrılacaktır. Örneğin, bir görev öğesi şöyle görünebilir:


    // src/components/TodoItem.js

    import React from 'react';
    import './TodoItem.css';

    function TodoItem({ todo, onEdit, onDelete, onToggleComplete }) {
        return (
            
todo-item ${todo.completed ? 'completed' : ''}}> onToggleComplete(todo.id, todo.completed)} />

{todo.title}

{todo.description}

); } export default TodoItem;

Bu component’ler bir araya geldiğinde, kullanıcıların etkileşimde bulunabileceği tam işlevli bir To-Do uygulaması ortaya çıkar. Kullanıcı yeni bir görev eklediğinde, form verileri API’ye gönderilir, API yanıt döndüğünde React state’i günceller ve arayüz otomatik olarak yeniden render edilir. Bu dinamik veri akışı, React’ın gücünü ve modern web uygulamalarında neden bu kadar popüler olduğunu açıkça göstermektedir. CSS ile bu component’lere stil ekleyerek daha çekici bir görünüm kazandırabilirsiniz. Örneğin, App.css, TodoForm.css, TodoList.css ve TodoItem.css dosyaları oluşturarak her bir component’in stilini ayrı ayrı yönetebilirsiniz.

İleri Düzey Konular ve Optimizasyonlar: Uygulamamızı Daha İyi Nasıl Hale Getiririz?

Temel To-Do uygulamamızı başarıyla geliştirdik, ancak modern bir web uygulamasının sadece temel işlevsellikten ibaret olmadığını biliyoruz. Güvenlik, performans ve dağıtım gibi konular, uygulamanın gerçek dünya senaryolarında başarılı olması için kritik öneme sahiptir. Bu bölümde, uygulamamızı daha güvenli, daha hızlı ve daha kolay yönetilebilir hale getirecek ileri düzey konuları ve optimizasyon tekniklerini keşfedeceğiz. Deneyimli geliştiriciler için değerli ipuçları sunarken, aynı zamanda yeni başlayanlara da gelecekteki projeleri için bir yol haritası çizeceğiz.

Kimlik Doğrulama ve Yetkilendirme: Güvenliği Nasıl Sağlarız?

Çoğu To-Do uygulamasında, her kullanıcının kendi görev listesi olmasını isteriz. Bu, kimlik doğrulama (kullanıcının kim olduğunu bilmek) ve yetkilendirme (kullanıcının ne yapmasına izin verildiğini bilmek) gerektirir. Django REST Framework, bu konuda birçok seçenek sunar. En yaygın ve modern yaklaşımlardan biri JWT (JSON Web Tokens) kullanmaktır. JWT, kullanıcı giriş yaptığında sunucu tarafından oluşturulan ve istemciye gönderilen şifreli bir belirteçtir. İstemci (React uygulamamız), bu belirteci sonraki tüm API isteklerinde göndererek kendini doğrular.

Backend (Django DRF) Tarafında JWT Entegrasyonu:

  1. Kurulum: pip install djangorestframework-simplejwt
  2. settings.py yapılandırması:
  3. 
                # todo_backend/settings.py
                INSTALLED_APPS = [
                    # ...
                    'rest_framework',
                    'rest_framework_simplejwt',
                    # ...
                ]
    
                REST_FRAMEWORK = {
                    'DEFAULT_AUTHENTICATION_CLASSES': (
                        'rest_framework_simplejwt.authentication.JWTAuthentication',
                    ),
                }
    
                from datetime import timedelta
                SIMPLE_JWT = {
                    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
                    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
                    'ROTATE_REFRESH_TOKENS': True,
                    'BLACKLIST_AFTER_ROTATION': True,
                    'ALGORITHM': 'HS256',
                    'SIGNING_KEY': SECRET_KEY, # Django'nun SECRET_KEY'ini kullanın
                    'VERIFYING_KEY': None,
                    'AUDIENCE': None,
                    'ISSUER': None,
                    'JWK_URL': None,
                    'LEEWAY': 0,
    
                    'AUTH_HEADER_TYPES': ('Bearer',),
                    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
                    'USER_ID_FIELD': 'id',
                    'USER_ID_CLAIM': 'user_id',
                    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
    
                    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
                    'TOKEN_TYPE_CLAIM': 'token_type',
                    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
    
                    'JTI_CLAIM': 'jti',
    
                    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
                    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
                    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
                }
                
  4. urls.py yapılandırması: Giriş ve token yenileme uç noktalarını ekleyin.
  5. 
                # todo_backend/urls.py
                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'),
                ]
                
  6. ViewSet’te İzin Sınıfları: Sadece giriş yapmış kullanıcıların kendi görevlerini görmesini sağlamak için api/views.py dosyasında IsAuthenticated ve IsOwner gibi izin sınıflarını kullanabilirsiniz.
  7. 
                # api/views.py
                from rest_framework.permissions import IsAuthenticated
                from .permissions import IsOwnerOrReadOnly # Kendi custom iznimizi yazabiliriz
    
                class TodoViewSet(viewsets.ModelViewSet):
                    serializer_class = TodoSerializer
                    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly] # Bu izinleri ekleyin
    
                    def get_queryset(self):
                        return Todo.objects.filter(user=self.request.user).order_by('-created_at')
    
                    def perform_create(self, serializer):
                        serializer.save(user=self.request.user)
                

    IsOwnerOrReadOnly gibi özel izin sınıfları, bir kullanıcının yalnızca kendi oluşturduğu öğeleri düzenleyip silebilmesini sağlarken, diğer öğeleri sadece okumasına izin verir. Bu, api/permissions.py gibi bir dosyada tanımlanabilir.

    Frontend (React) Tarafında JWT Kullanımı:

    React uygulamasında, kullanıcı giriş yaptıktan sonra alınan JWT token’larını (access ve refresh token) yerel depolama (localStorage) veya bir context API kullanarak saklayabilirsiniz. Her API isteğinde, axios‘un interceptor’larını kullanarak Authorization başlığına Bearer <access_token> eklemelisiniz. Token süresi dolduğunda, refresh token ile yeni bir access token almayı denemelisiniz.

    
        // src/api.js (örnek bir axios yapılandırması)
        import axios from 'axios';
    
        const apiClient = axios.create({
            baseURL: 'http://localhost:8000/api/',
            headers: {
                'Content-Type': 'application/json',
            },
        });
    
        apiClient.interceptors.request.use(config => {
            const token = localStorage.getItem('accessToken');
            if (token) {
                config.headers.Authorization = Bearer ${token};
            }
            return config;
        }, error => {
            return Promise.reject(error);
        });
    
        // Token yenileme mantığı da buraya eklenebilir
        // apiClient.interceptors.response.use(...)
    
        export default apiClient;
        

    Uzman İpucu: JWT token’larını localStorage‘da saklamak XSS saldırılarına karşı riskli olabilir. Daha güvenli bir yaklaşım için, token’ları HTTP-only çerezlerde saklamayı düşünebilirsiniz. Ancak bu, CORS ve Same-Site policy gibi konularda ek yapılandırma gerektirecektir.

    Performans Optimizasyonları: Uygulamamızı Nasıl Hızlandırırız?

    Uygulamanın kullanıcı sayısı arttıkça veya veri miktarı çoğaldıkça performans kritik hale gelir. Hem backend hem de frontend tarafında yapabileceğimiz birçok optimizasyon vardır.

    Backend (Django) Performans İpuçları:

  • Veritabanı Sorgu Optimizasyonu: N+1 sorgu probleminden kaçınmak için select_related() ve prefetch_related() kullanın. Bu, ilişkili verileri tek bir sorguda çekerek veritabanı yükünü azaltır.
  • Caching: Sık erişilen ama nadiren değişen veriler için Django’nun caching framework’ünü veya Redis gibi harici bir cache sistemini kullanın.
  • Asenkron Görevler: Uzun süren işlemleri (e-posta gönderme, resim işleme) Celery gibi bir asenkron görev kuyruğu ile arka plana taşıyın.
  • API Sınırlaması (Throttling): Kötü niyetli veya aşırı istekleri önlemek için DRF’nin throttling özelliklerini kullanın.

Frontend (React) Performans İpuçları:

  • React.memo, useCallback, useMemo: Gereksiz yeniden render’ları önlemek için bu hook’ları ve HOC’ları kullanın. Özellikle büyük listeler render ederken fark yaratırlar.
  • Lazy Loading (Tembel Yükleme): Uygulamanın başlangıç yükleme süresini azaltmak için React.lazy() ve Suspense ile component’leri sadece ihtiyaç duyulduğunda yükleyin.
  • Sanallaştırma (Virtualization): Çok uzun listeler için (örneğin 1000’den fazla görev) React Window veya React Virtualized gibi kütüphanelerle sadece görünürdeki öğeleri render ederek performansı artırın.
  • Resim Optimizasyonu: Yüksek çözünürlüklü resimler yerine optimize edilmiş, uygun boyutlarda resimler kullanın.

Dağıtım (Deployment) Stratejileri: Uygulamamızı Canlıya Nasıl Alırız?

Uygulamayı geliştirdikten sonra, herkesin erişebileceği bir sunucuya dağıtmak gerekir. Django ve React’ın ayrı ayrı dağıtılması genellikle en iyi yaklaşımdır.

  • Backend (Django) Dağıtımı:
    • Web Sunucusu: Gunicorn veya uWSGI gibi bir WSGI sunucusu ile Django uygulamasını çalıştırın.
    • Ters Proxy: Nginx veya Apache gibi bir ters proxy sunucusu, gelen istekleri Gunicorn’a yönlendirir ve statik dosyaları sunar.
    • Veritabanı: PostgreSQL veya MySQL gibi üretim seviyesi bir veritabanı kullanın.
    • Platformlar: Heroku, AWS EC2, DigitalOcean Droplet, Google Cloud Run gibi platformlara dağıtabilirsiniz.
  • Frontend (React) Dağıtımı:
    • Statik Dosya Sunucusu: React uygulaması derlendiğinde (npm run build), statik HTML, CSS ve JavaScript dosyaları oluşur. Bu dosyaları Nginx, Apache, Netlify, Vercel veya AWS S3/CloudFront gibi bir statik dosya sunucusundan yayınlayabilirsiniz.
    • CDN: İçerik Dağıtım Ağları (CDN), statik dosyalarınızı dünya genelinde önbelleğe alarak kullanıcılarınıza daha hızlı erişim sağlar.
  • Konteynerleştirme (Docker): Hem Django hem de React uygulamalarını Docker konteynerlerine alarak dağıtım sürecini standartlaştırabilir ve basitleştirebilirsiniz. Docker Compose ile her iki servisi de yerel ortamda kolayca yönetebilir, üretimde Kubernetes gibi orkestrasyon araçlarıyla ölçeklendirebilirsiniz.

Vaka Analizi: Büyük Ölçekli Bir Uygulamada Performans Darboğazları ve Çözümleri

Bir e-ticaret platformunun “ürün listeleme” sayfasının yavaş yüklendiğini varsayalım. İlk analizde, sayfanın 500’den fazla ürünü ve her ürün için ortalama 3 resim çekmesi gerektiği ortaya çıktı. Backend tarafında, her ürün için ayrı ayrı resim sorguları yapıldığı (N+1 problemi) ve veritabanından çekilen verilerin tam olarak optimize edilmediği tespit edildi. Çözüm olarak, Django’da select_related('category') ve prefetch_related('images') kullanılarak ürün, kategori ve resim verileri tek veya çok az sayıda sorguyla çekildi. Ayrıca, sık güncellenmeyen ürün bilgileri için Redis ile 15 dakikalık bir cache mekanizması eklendi. Frontend tarafında ise, ürün resimleri için lazy loading uygulandı ve React’ın React.memo HOC’u ile ürün kartı component’leri optimize edildi, böylece sadece değişen kartlar yeniden render edildi. Bu optimizasyonlar sonucunda sayfa yükleme süresi %60 oranında azaldı, kullanıcı deneyimi önemli ölçüde iyileşti.

Bu ileri düzey konular, uygulamanızı sadece işlevsel kılmakla kalmaz, aynı zamanda onu daha profesyonel, güvenli ve performanslı hale getirir. Geliştirme yolculuğunuzda bu konuları göz önünde bulundurarak çok daha başarılı projelere imza atabilirsiniz.

Sonuç: Django ve React Birlikte Geleceğe Yönelik Bir Çözüm mü?

Bu makalede, Django’nun sağlam backend yetenekleri ile React’ın dinamik frontend gücünü birleştirerek nasıl modern bir To-Do uygulaması geliştirebileceğimizi adım adım inceledik. Django REST Framework ile güçlü ve ölçeklenebilir bir API oluşturmanın, React ile ise kullanıcı dostu ve etkileşimli bir arayüz inşa etmenin ne kadar kolay olduğunu gördük. Her iki teknolojinin de kendi alanlarındaki uzmanlığı, bir araya geldiklerinde decoupled mimarinin sunduğu tüm avantajları ortaya çıkararak geliştirme sürecini hızlandırıyor ve uygulamanın uzun vadeli sürdürülebilirliğini sağlıyor. Güvenlik, performans optimizasyonları ve dağıtım stratejileri gibi ileri düzey konulara değinerek, projenizi bir sonraki seviyeye taşıyacak değerli bilgiler edindiniz. Django ve React ikilisi, sadece bir To-Do uygulaması için değil, aynı zamanda büyük ölçekli ve karmaşık kurumsal uygulamalar için de kanıtlanmış, geleceğe yönelik, esnek ve güçlü bir çözüm sunmaktadır. Bu rehber, kendi web geliştirme yolculuğunuzda size ilham vermesini ve yeni projeleriniz için sağlam bir başlangıç noktası olmasını umuyoruz.

Sıkça Sorulan Sorular

Django REST Framework yerine Flask veya FastAPI kullanabilir miyim?
Evet, kesinlikle. Django REST Framework, Django’nun ORM’i ve admin paneli gibi özellikleriyle entegre olduğu için hızlı bir başlangıç sağlar. Ancak Flask (Flask-RESTful veya Flask-RESTX ile) veya FastAPI (yüksek performanslı ve modern bir seçenek) gibi başka Python tabanlı framework’leri de backend API’nizi oluşturmak için kullanabilirsiniz. React frontend’i, backend’in hangi teknolojiyle yazıldığından bağımsız olarak RESTful API ile iletişim kurabilir.
React yerine Angular veya Vue.js tercih edebilir miyim?
Elbette. React, component tabanlı mimarisi ve Virtual DOM’u ile popüler bir seçim olsa da, Angular ve Vue.js de modern frontend geliştirme için harika alternatiflerdir. Her üç kütüphane/framework de benzer prensiplere dayanır ve API ile iletişim kurma yeteneğine sahiptir. Seçiminiz, projenizin gereksinimlerine, ekibinizin uzmanlığına ve kişisel tercihinize bağlıdır.
Frontend ve backend aynı sunucuda mı olmalı?
Geliştirme ortamında ayrı sunucularda (genellikle localhost:8000 ve localhost:3000) çalıştırılmaları yaygındır. Üretim ortamında ise, genellikle frontend’in statik dosyaları (HTML, CSS, JS) bir CDN veya Nginx gibi bir web sunucusu üzerinden sunulurken, backend ayrı bir sunucuda (Gunicorn/uWSGI arkasında Nginx ile) çalışır. Bu ayrım, her iki katmanın bağımsız olarak ölçeklenmesine ve yönetilmesine olanak tanır.
CORS hatası nedir ve nasıl çözülür?
CORS (Cross-Origin Resource Sharing), bir web sayfasının başka bir “origin”den (farklı bir alan adı, protokol veya port) kaynakları talep etmesini kısıtlayan bir web tarayıcısı güvenlik mekanizmasıdır. Bizim örneğimizde, React frontend (localhost:3000) Django backend’ine (localhost:8000) istek gönderdiğinde bu bir CORS hatasına neden olabilir. Django tarafında django-cors-headers kütüphanesini kurup yapılandırarak bu hatayı çözdük. Üretimde CORS_ALLOWED_ORIGINS ayarını kullanarak sadece güvenilir frontend adreslerine izin vermelisiniz.
Mobil uygulama geliştirmek için bu mimari uygun mu?
Evet, kesinlikle uygun. Bu decoupled mimari, aynı Django backend API’sini kullanarak React Native (mobil uygulamalar için React tabanlı bir framework) ile iOS ve Android için mobil uygulamalar geliştirebileceğiniz anlamına gelir. API’niz, mobil uygulamanız için de veri kaynağı olarak hizmet verebilir, böylece backend kodunu yeniden yazmanıza gerek kalmaz. Bu, tam yığın (full-stack) geliştiriciler için oldukça verimli bir yaklaşımdır.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık