Django Admin Paneli: Özelleştirme İpuçları

Django'nun en güçlü yanlarından biri olan Admin paneli, özellikle veritabanı yönetimini ve içerik girişini inanılmaz derecede kolaylaştırır. 


Django'yu diğer web framework'lerinden ayıran en büyük özelliklerinden biri, geliştiricilere anında kullanıma hazır, dinamik ve son derece özelleştirilebilir bir yönetim paneli (Admin paneli) sunmasıdır. Bu makalede, Django Admin panelinin temel kullanımından gelişmiş özelleştirme tekniklerine kadar her şeyi adım adım inceleyeceğiz.

1. Admin Paneline Giriş ve Superuser Oluşturma

Django projenizi oluşturduğunuzda admin paneli varsayılan olarak gelir. Ancak panele giriş yapabilmek için en yetkili kullanıcı olan bir "superuser" oluşturmanız gerekir.

Terminalinizi açın ve proje dizinindeyken şu komutu çalıştırın:

Bash:
python manage.py createsuperuser

Sizden bir kullanıcı adı, e-posta adresi ve şifre isteyecektir. Bilgileri girdikten sonra geliştirme sunucunuzu başlatın (python manage.py runserver) ve tarayıcınızdan http://127.0.0.1:8000/admin/ adresine giderek giriş yapın.

2. Modelleri Admin Paneline Kaydetmek

Admin panelinde kendi oluşturduğumuz veritabanı tablolarını (modelleri) görebilmek için onları kaydetmemiz gerekir. Örnek olarak bir eğitim sistemindeki Ogrenci modelini ele alalım.

models.py:

Python:
from django.db import models

class Ogrenci(models.Model):
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)
    numara = models.CharField(max_length=10, unique=True)
    kayit_tarihi = models.DateField(auto_now_add=True)
    mezun_mu = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.numara} - {self.ad} {self.soyad}"

Bu modeli admin panelinde görünür kılmak için uygulamanızın admin.py dosyasını düzenlemelisiniz:

admin.py (Temel Kayıt):

Python:
from django.contrib import admin
from .models import Ogrenci

admin.site.register(Ogrenci)

3. ModelAdmin ile Paneli Özelleştirme

Varsayılan görünüm işimizi görse de, kayıt sayısı arttıkça verileri yönetmek zorlaşır. İşte burada ModelAdmin sınıfı devreye girer.

admin.py (Gelişmiş Kayıt):

Python:
from django.contrib import admin
from .models import Ogrenci

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    # Listeleme ekranında görünecek sütunlar
    list_display = ('numara', 'ad', 'soyad', 'kayit_tarihi', 'mezun_mu')
    
    # Sağ tarafa filtreleme menüsü ekler
    list_filter = ('mezun_mu', 'kayit_tarihi')
    
    # Arama çubuğu ekler (ad, soyad veya numaraya göre aranabilir)
    search_fields = ('ad', 'soyad', 'numara')
    
    # Varsayılan sıralamayı belirler (numaraya göre artan)
    ordering = ('numara',)
    
    # Sayfa başına gösterilecek kayıt sayısı
    list_per_page = 20

Önemli ModelAdmin Özellikleri:

  • list_display: Nesnelerin liste sayfasında hangi alanlarının tablo sütunu olarak gösterileceğini belirler.

  • search_fields: Arama kutucuğu ekler ve aramanın hangi veritabanı alanlarında yapılacağını belirtir.

  • list_filter: Belirli alanlara (özellikle Boolean, Date veya ForeignKey) göre filtreleme imkanı sunar.

4. Admin Paneline Özel Eylemler (Actions) Eklemek

Bazen birden fazla kaydı aynı anda güncellemek isteyebilirsiniz. Örneğin, seçili öğrencilerin hepsini tek tıkla "Mezun" durumuna getirmek isteyelim.

admin.py:

Python:
from django.contrib import admin
from .models import Ogrenci

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    list_display = ('numara', 'ad', 'soyad', 'mezun_mu')
    actions = ['mezun_yap']

    @admin.action(description='Seçili öğrencileri mezun yap')
    def mezun_yap(self, request, queryset):
        guncellenen = queryset.update(mezun_mu=True)
        self.message_user(request, f"{guncellenen} öğrenci başarıyla mezun edildi.")

Bu kodu eklediğinizde, admin panelindeki açılır eylem menüsüne "Seçili öğrencileri mezun yap" seçeneğinin eklendiğini göreceksiniz.

5. Başlık ve Site İsimlerini Değiştirme

Admin panelinin sol üst köşesinde yazan standart "Django yönetimi" yazısını kendi projenize uygun hale getirebilirsiniz. Bunun için genellikle ana projenin urls.py dosyasını kullanmak en pratik yoldur.

urls.py:

Python:
from django.contrib import admin
from django.urls import path

# Admin paneli başlık özelleştirmeleri
admin.site.site_header = "Okul Yönetim Sistemi"
admin.site.site_title = "Okul Admin Portalı"
admin.site.index_title = "Yönetim Paneline Hoş Geldiniz"

urlpatterns = [
    path('admin/', admin.site.urls),
]

Sonuç

Django Admin paneli, veritabanı yönetimi için tekerleği yeniden icat etmenizi engeller. Birkaç satır kod ile arama, filtreleme, sayfalama ve toplu işlemler yapabileceğiniz profesyonel bir arayüz elde edersiniz. Bu makaledeki özelleştirmeler, projelerinizin yönetim arayüzünü hem sizin hem de son kullanıcılar için çok daha verimli hale getirecektir.


.

6. Admin Paneli HTML Şablonlarını (Templates) Özelleştirmek

Django Admin paneli arka planda klasik Django HTML şablonlarını kullanır. Kendi projemizde aynı isimde klasör ve dosyalar oluşturarak bu varsayılan şablonları "ezebiliriz" (override). Örneğin, admin panelinin en üstüne projenize özel bir geri dönüş butonu veya logonuzu eklemek isteyebilirsiniz.

Adım 1: Klasör Yapısını Kurmak

Öncelikle settings.py dosyanızdaki TEMPLATES ayarında şablon dizininizin tanımlı olduğundan emin olun:

Python
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'], # Bu satırın eklendiğinden emin olun
        'APP_DIRS': True,
        # ...
    },
]

Adım 2: Şablon Dosyasını Oluşturmak

Projenizin ana dizininde sırasıyla templates ve onun içinde admin adında klasörler oluşturun. Daha sonra admin klasörünün içine base_site.html adında bir dosya açın.

Adım 3: Kodu Eklemek

Oluşturduğumuz templates/admin/base_site.html dosyasının içine şu kodları yapıştırarak orijinal şablonu genişletip kendi başlığımızı ekleyebiliriz:

HTML
{% extends "admin/base_site.html" %}

{% block branding %}
    <h1 id="site-name">
        <a href="{% url 'admin:index' %}">
            <span style="color: #417690; font-weight: bold;">Okul Bilgi Sistemi Admin Portalı</span>
        </a>
    </h1>
    <p style="margin: 5px 0 0 10px;">
        <a href="/" style="color: #999;">&larr; Siteye Geri Dön</a>
    </p>
{% endblock %}

Artık sayfa yenilendiğinde sol üst köşede kendi tasarımınızın ve ana sayfaya dönüş linkinin yer aldığını göreceksiniz. change_form.html veya change_list.html gibi dosyaları ezerek form ve liste sayfalarına özel butonlar da ekleyebilirsiniz.

7. Üretim (Production) Ortamında Admin Statik Dosyalarını Yayınlamak

Projeyi geliştirirken her şey harika görünür ancak uygulamanızı bir Pardus sunucuya taşıyıp settings.py içinde DEBUG = False yaptığınızda büyük bir sürprizle karşılaşırsınız: Admin paneli tamamen bozulmuş, renksiz ve darmadağın bir HTML sayfasına dönüşmüştür.

Bunun sebebi, üretim ortamında Django'nun artık CSS, JavaScript ve görsel gibi statik dosyaları kendi başına sunmayı bırakmasıdır. Bu görevi Nginx veya Apache gibi güçlü bir web sunucusuna devretmemiz gerekir.

Adım 1: Statik Dosya Ayarlarını Yapılandırmak

settings.py dosyanızın en altına şu ayarları ekleyin:

Python
STATIC_URL = '/static/'
# Sunucudaki tüm statik dosyaların toplanacağı ana dizin
STATIC_ROOT = BASE_DIR / 'staticfiles' 

Adım 2: Dosyaları Toplamak (Collectstatic)

Terminalde aşağıdaki komutu çalıştırarak Django'nun (admin paneli dahil) kullandığı tüm statik dosyaları staticfiles klasörüne kopyalamasını sağlayın:

Bash
python manage.py collectstatic

Bu işlemden sonra admin panelinin CSS ve JS dosyalarının belirlediğiniz klasöre kopyalandığını göreceksiniz.

Adım 3: Pardus Üzerinde Nginx Yapılandırması

Son olarak, web sunucunuza (örneğin Nginx) /static/ uzantılı bir istek geldiğinde bu klasöre bakmasını söylemelisiniz. Nginx ayar dosyanızdaki (/etc/nginx/sites-available/projeniz) server bloğunun içine şu satırları ekleyin:

Nginx
server {
    # ... diğer ayarlar (listen, server_name vs.) ...

    location /static/ {
        # Projenizdeki staticfiles klasörünün tam yolu
        alias /var/www/projeniz/staticfiles/; 
    }

    location / {
        # Gunicorn veya uWSGI yönlendirmeleri
        proxy_pass http://127.0.0.1:8000;
        # ...
    }
}

Nginx'i yeniden başlattığınızda (sudo systemctl restart nginx), admin paneliniz Pardus sunucunuz üzerinde tüm stilleriyle birlikte eksiksiz ve güvenli bir şekilde çalışmaya başlayacaktır.




📌 1️⃣ Django Admin Paneli Nedir?

Django Admin, Django framework’ü ile birlikte hazır gelen bir yönetim panelidir.

👉 Veritabanındaki verileri:

  • Listeleyebiliriz

  • Ekleyebiliriz

  • Güncelleyebiliriz

  • Silebiliriz (CRUD)

Hem de hiç HTML yazmadan!


📌 2️⃣ Admin Paneli Aktif mi Kontrol Edelim

settings.py dosyasında şu satırların olduğundan emin olun:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Bu uygulamalar Django’nun temel sistemleridir.


📌 3️⃣ Superuser (Yönetici) Oluşturma

Admin paneline giriş için yönetici hesabı gerekir.

Terminalde:

python manage.py createsuperuser

Sizden:

  • Kullanıcı adı

  • Email

  • Şifre

isteyecek.


📌 4️⃣ Admin Panelini Çalıştırma

Sunucuyu başlatalım:

python manage.py runserver

Tarayıcıdan:

http://127.0.0.1:8000/admin

🎉 Django’nun hazır admin paneli karşınızda!


📌 5️⃣ Modeli Admin Paneline Eklemek

Örnek model oluşturalım:

# models.py
from django.db import models

class Ogrenci(models.Model):
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)
    yas = models.IntegerField()
    aktif = models.BooleanField(default=True)

    def __str__(self):
        return f"{self.ad} {self.soyad}"

Migration yapalım:

python manage.py makemigrations
python manage.py migrate

📌 Admin’e Model Kaydı

admin.py dosyasına:

from django.contrib import admin
from .models import Ogrenci

admin.site.register(Ogrenci)

Artık admin panelinde Ogrenci modeli görünecek.


📌 6️⃣ Admin Panelini Özelleştirme

Django Admin’i güçlü yapan şey özelleştirilebilir olmasıdır.


🎯 Liste Görünümünü Düzenleme

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    list_display = ("ad", "soyad", "yas", "aktif")

Açıklama:

  • list_display → tabloda hangi sütunlar görünecek


🎯 Filtre Ekleme

list_filter = ("aktif", "yas")

Sağ tarafta filtre alanı oluşur.


🎯 Arama Özelliği

search_fields = ("ad", "soyad")

Arama kutusu ekler.


🎯 Sıralama

ordering = ("ad",)

🎯 Sayfa Başına Kayıt

list_per_page = 10

📌 7️⃣ Admin Form Alanlarını Gruplama

fieldsets = (
    ("Kişisel Bilgiler", {
        "fields": ("ad", "soyad")
    }),
    ("Durum Bilgisi", {
        "fields": ("yas", "aktif")
    }),
)

Bu kod formu başlıklarla ayırır.


📌 8️⃣ Salt Okunur Alan Yapma

readonly_fields = ("ad",)

📌 9️⃣ Otomatik Alan Ekleme (Tarih)

Modeli güncelleyelim:

created_at = models.DateTimeField(auto_now_add=True)

Admin’de:

readonly_fields = ("created_at",)

📌 🔟 Inline (İlişkili Modeller)

Örnek: Öğrenci ve Not modeli

class Not(models.Model):
    ogrenci = models.ForeignKey(Ogrenci, on_delete=models.CASCADE)
    ders = models.CharField(max_length=50)
    puan = models.IntegerField()

Admin’de:

class NotInline(admin.TabularInline):
    model = Not
    extra = 1

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    inlines = [NotInline]

👉 Artık öğrenci eklerken notları da ekleyebiliriz.


📌 11️⃣ Admin Panel Başlığını Değiştirme

admin.py içine:

admin.site.site_header = "Okul Yönetim Paneli"
admin.site.site_title = "Okul Admin"
admin.site.index_title = "Yönetim Sistemi"

📌 12️⃣ Yetkilendirme (Permission Sistemi)

Django otomatik olarak şunları oluşturur:

  • add

  • change

  • delete

  • view

Kullanıcıları:
Admin → Users → Permissions bölümünden ayarlayabilirsiniz.


📌 13️⃣ Admin Panel Güvenliği

Öneriler:

✅ Güçlü şifre kullan
✅ DEBUG = False (Canlı sunucuda)
✅ HTTPS kullan
✅ Admin URL değiştirilebilir

path("panelim/", admin.site.urls),

📌 14️⃣ Gerçek Hayatta Kullanım Senaryosu

Admin paneli şunlar için idealdir:

  • Okul otomasyonu

  • Kütüphane sistemi

  • Stok takip

  • Blog yönetimi

  • İçerik yönetim sistemi (CMS)

Ama genelde kullanıcıya açık arayüz için kullanılmaz.


📌 15️⃣ Mini Lab Uygulaması

🎯 Görev:

  1. Ogrenci modeli oluştur

  2. Admin’e ekle

  3. list_display ekle

  4. search_fields ekle

  5. list_filter ekle

  6. fieldsets kullan

  7. Inline ile Not modeli bağla


🎯 Django Admin’in Avantajları

ÖzellikAçıklama
Hazır gelirEk kurulum yok
CRUD hazırKod yazmadan veri yönetimi
GüvenliYetkilendirme sistemi var
Hızlı geliştirmePrototip için ideal

🏁 Sonuç

Django Admin:

  • Hızlıdır

  • Güvenlidir

  • Özelleştirilebilir

  • Profesyonel projelerde backend yönetimi için idealdir


Şimdi Django Admin Paneli’ni modern ve şık bir görünüme kavuşturalım.

Admin paneli varsayılan olarak sade bir tasarıma sahiptir. Ancak istersek:

  • 🎨 Renkleri değiştirebilir

  • 🌙 Dark Mode yapabilir

  • 🔲 Daha modern kart tasarımı ekleyebilir

  • 📊 Dashboard görünümünü geliştirebiliriz

Bunu 2 farklı yöntemle yapacağız:


🚀 YÖNTEM 1: Hazır Modern Admin Teması (En Profesyonel Yöntem)

En popüler modern Django admin teması:

⭐ Django Jazzmin

Modern, responsive ve profesyonel görünümlüdür.


📌 1️⃣ Kurulum

Terminal:

pip install django-jazzmin

📌 2️⃣ settings.py Düzenleme

INSTALLED_APPS = [
    "jazzmin",  # EN ÜSTE
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

⚠️ Jazzmin mutlaka django.contrib.admin’dan önce olmalı.


📌 3️⃣ Çalıştır

python manage.py runserver

Admin paneline gir:

http://127.0.0.1:8000/admin

🎉 Artık modern bir admin panelin var!


📌 4️⃣ Jazzmin Özelleştirme

settings.py içine ekle:

JAZZMIN_SETTINGS = {
    "site_title": "Okul Yönetim Sistemi",
    "site_header": "Okul Admin",
    "welcome_sign": "Yönetim Paneline Hoşgeldiniz",
    "copyright": "Bilişim Bölümü",
    "topmenu_links": [
        {"name": "Ana Sayfa", "url": "admin:index"},
    ],
    "show_sidebar": True,
    "navigation_expanded": True,
}

🎨 Renk Değiştirme

JAZZMIN_SETTINGS = {
    "theme": "flatly",  # cerulean, cosmo, flatly, darkly vb.
}

Dark mode için:

"theme": "darkly",

🚀 YÖNTEM 2: Manuel CSS ile Modernleştirme (Öğretici Yöntem)

Bu yöntemle admin paneline kendi CSS dosyamızı ekleyeceğiz.


📌 1️⃣ Static Klasörü Oluştur

proje/
   static/
       css/
           admin.css

📌 2️⃣ settings.py Static Ayarı

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static",
]

📌 3️⃣ Admin’e CSS Bağlama

admin.py içine:

from django.contrib import admin

class MyAdminSite(admin.AdminSite):
    class Media:
        css = {
            "all": ("css/admin.css",)
        }

admin.site.__class__ = MyAdminSite

📌 4️⃣ Modern CSS Örneği

static/css/admin.css

/* Genel Arka Plan */
body {
    background-color: #f4f6f9;
}

/* Başlık Alanı */
#header {
    background: linear-gradient(90deg, #1e3c72, #2a5298);
}

/* Butonlar */
.button, input[type=submit] {
    background-color: #4CAF50 !important;
    border-radius: 8px !important;
    padding: 8px 15px !important;
}

/* Tablolar */
table {
    border-radius: 10px;
    overflow: hidden;
}

/* Hover efekti */
tr:hover {
    background-color: #e6f2ff !important;
}

Sunucuyu yeniden başlat:

python manage.py runserver

🌙 BONUS: Admin Dark Mode

body {
    background-color: #1e1e1e;
    color: white;
}

.module h2 {
    background-color: #333;
}

🚀 YÖNTEM 3: Profesyonel Dashboard (Alternatif Tema)

Bir diğer modern tema:

⭐ django-admin-interface

Kurulum:

pip install django-admin-interface

Bu tema renkleri admin panel içinden değiştirmenizi sağlar.


🎯 Hangisini Kullanmalıyım?

DurumÖneri
Hızlı ve profesyonel        Jazzmin
Öğrenmek istiyorum        Manuel CSS
Panelden renk değiştirmek        django-admin-interface

🏫 Okul Projesi İçin Önerim

Sen okul projeleri yapıyorsun 👨‍💻
En temiz ve etkileyici sonuç için:

👉 Jazzmin + Darkly tema kullan
👉 Logo ekle
👉 Sidebar aktif yap
👉 Dashboard’a model ikonları ekle


Şimdi adım adım profesyonel seviyede modern bir Django Admin sistemi yapıyoruz.

Kullanacağımız temel yapı:

  • 🎨 Tema: Django Jazzmin

  • 📊 Grafik: Chart.js

  • 🔐 Yetki: Django’nun built-in permission sistemi

  • 🏫 Senaryo: Okul Otomasyon Admin Paneli


🎨 1️⃣ Admin’e Logo Ekleyelim

📌 Logo Dosyası

static/img/logo.png içine okul logosunu koy.


📌 settings.py

JAZZMIN_SETTINGS = {
    "site_title": "Okul Yönetim Sistemi",
    "site_header": "Bilişim Okulu",
    "site_brand": "Okul Admin",
    "site_logo": "img/logo.png",
    "login_logo": "img/logo.png",
    "site_logo_classes": "img-circle",
}

Artık:

  • Login ekranında logo var

  • Sidebar’da logo var

  • Profesyonel görünüm oluştu


📊 2️⃣ Dashboard’a Grafik Ekleyelim

Amaç:

  • Kaç öğrenci var?

  • Kaç öğretmen var?

  • Kaç aktif kayıt var?


📌 models.py

class Ogrenci(models.Model):
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)
    aktif = models.BooleanField(default=True)

class Ogretmen(models.Model):
    ad = models.CharField(max_length=50)
    brans = models.CharField(max_length=50)

📌 admin.py Dashboard View Ekleyelim

from django.urls import path
from django.template.response import TemplateResponse
from django.db.models import Count
from .models import Ogrenci, Ogretmen
from django.contrib import admin

class MyAdminSite(admin.AdminSite):
    site_header = "Okul Yönetim Paneli"

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path("dashboard/", self.admin_view(self.dashboard))
        ]
        return custom_urls + urls

    def dashboard(self, request):
        ogrenci_sayisi = Ogrenci.objects.count()
        ogretmen_sayisi = Ogretmen.objects.count()
        aktif_ogrenci = Ogrenci.objects.filter(aktif=True).count()

        context = dict(
            self.each_context(request),
            ogrenci_sayisi=ogrenci_sayisi,
            ogretmen_sayisi=ogretmen_sayisi,
            aktif_ogrenci=aktif_ogrenci,
        )
        return TemplateResponse(request, "admin/dashboard.html", context)

admin_site = MyAdminSite(name="myadmin")

📌 templates/admin/dashboard.html

{% extends "admin/base_site.html" %}
{% block content %}
<h1>Okul Dashboard</h1>

<canvas id="myChart"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');

new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Toplam Öğrenci', 'Aktif Öğrenci', 'Öğretmen'],
        datasets: [{
            label: 'Okul Verileri',
            data: [{{ ogrenci_sayisi }}, {{ aktif_ogrenci }}, {{ ogretmen_sayisi }}],
        }]
    }
});
</script>

{% endblock %}

🎉 Admin içinde grafik çıktı.


🔐 3️⃣ Rol Bazlı Admin Tasarlayalım

Django otomatik permission üretir:

  • add

  • change

  • delete

  • view


📌 Rol 1: Müdür

  • Her şeyi görebilir

  • Silme yetkisi var

📌 Rol 2: Öğretmen

  • Sadece öğrenci görebilir

  • Silme yok


📌 Öğretmen Rolünü Sınırlandırma

class OgrenciAdmin(admin.ModelAdmin):

    def has_delete_permission(self, request, obj=None):
        if request.user.groups.filter(name="Ogretmen").exists():
            return False
        return True

📌 Group Oluşturma

Admin → Users → Groups
Yeni grup: Ogretmen

Permission olarak sadece:

  • view_ogrenci

  • change_ogrenci

ver.


🏫 4️⃣ TAM MODERN OKUL OTOMASYON ADMIN

🎯 Önerilen Modeller

class Sinif(models.Model):
    ad = models.CharField(max_length=20)

class Ogrenci(models.Model):
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)
    sinif = models.ForeignKey(Sinif, on_delete=models.CASCADE)
    aktif = models.BooleanField(default=True)

class Ders(models.Model):
    ad = models.CharField(max_length=50)

class Not(models.Model):
    ogrenci = models.ForeignKey(Ogrenci, on_delete=models.CASCADE)
    ders = models.ForeignKey(Ders, on_delete=models.CASCADE)
    puan = models.IntegerField()

🎨 Admin Modern Görünüm

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    list_display = ("ad", "soyad", "sinif", "aktif")
    list_filter = ("sinif", "aktif")
    search_fields = ("ad", "soyad")
    list_per_page = 10

💎 Profesyonel Dokunuşlar

Jazzmin ayarına ikon ekleyelim:

JAZZMIN_SETTINGS = {
    "icons": {
        "app.Ogrenci": "fas fa-user",
        "app.Ogretmen": "fas fa-chalkboard-teacher",
        "app.Sinif": "fas fa-school",
        "app.Ders": "fas fa-book",
    }
}

🚀 Sonuç

Artık admin panelin:

✅ Modern tasarımlı
✅ Logo’lu
✅ Grafik dashboard’lu
✅ Rol bazlı yetkili
✅ Okul otomasyonu yapısında

Profesyonel seviyede 🎯


Şimdi okul otomasyonunu profesyonel seviyeye taşıyoruz.

Kullanacağımız yapılar:

  • Tema: Django Jazzmin

  • Grafik: Chart.js

  • Excel işlemleri: pandas

  • PDF üretimi: ReportLab


📊 1️⃣ Not Ortalaması Otomatik Hesaplama

📌 models.py

class Not(models.Model):
    ogrenci = models.ForeignKey("Ogrenci", on_delete=models.CASCADE)
    ders = models.ForeignKey("Ders", on_delete=models.CASCADE)
    puan = models.IntegerField()

📌 Ogrenci Modeline Ortalama Property

from django.db.models import Avg

class Ogrenci(models.Model):
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)

    def ortalama(self):
        ort = self.not_set.aggregate(Avg("puan"))["puan__avg"]
        return round(ort, 2) if ort else 0

📌 Admin’de Gösterelim

@admin.register(Ogrenci)
class OgrenciAdmin(admin.ModelAdmin):
    list_display = ("ad", "soyad", "ortalama")

🎉 Artık admin listesinde ortalama görünüyor.


📥 2️⃣ Excel’den Öğrenci Import

📌 Kurulum

pip install pandas openpyxl

📌 admin.py içine import fonksiyonu

import pandas as pd
from django.shortcuts import render, redirect
from django.urls import path
from .models import Ogrenci

class OgrenciAdmin(admin.ModelAdmin):

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path("import-excel/", self.admin_site.admin_view(self.import_excel))
        ]
        return custom_urls + urls

    def import_excel(self, request):
        if request.method == "POST":
            excel_file = request.FILES["excel_file"]
            df = pd.read_excel(excel_file)

            for _, row in df.iterrows():
                Ogrenci.objects.create(
                    ad=row["ad"],
                    soyad=row["soyad"],
                )
            self.message_user(request, "Excel başarıyla yüklendi")
            return redirect("..")

        return render(request, "admin/import_excel.html")

📌 import_excel.html

{% extends "admin/base_site.html" %}
{% block content %}
<h2>Excel ile Öğrenci Yükle</h2>
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="excel_file">
    <button type="submit">Yükle</button>
</form>
{% endblock %}

Excel formatı:

adsoyad

📤 3️⃣ PDF Karne Oluşturma

📌 Kurulum

pip install reportlab

📌 views.py

from reportlab.pdfgen import canvas
from django.http import HttpResponse
from .models import Ogrenci

def karne_pdf(request, ogrenci_id):
    ogrenci = Ogrenci.objects.get(id=ogrenci_id)

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="karne.pdf"'

    p = canvas.Canvas(response)
    p.drawString(100, 800, f"Öğrenci: {ogrenci.ad} {ogrenci.soyad}")
    p.drawString(100, 780, f"Ortalama: {ogrenci.ortalama()}")

    y = 750
    for not_obj in ogrenci.not_set.all():
        p.drawString(100, y, f"{not_obj.ders.ad} : {not_obj.puan}")
        y -= 20

    p.showPage()
    p.save()
    return response

🎉 Artık PDF karne indirilebilir.


🌙 4️⃣ Full Dark Mode Admin

Jazzmin ayarına:

JAZZMIN_SETTINGS = {
    "theme": "darkly",
    "dark_mode_theme": "darkly",
}

Ek CSS:

body {
    background-color: #121212 !important;
}
.card {
    background-color: #1e1e1e !important;
}

📱 5️⃣ Mobil Uyumlu Özel Dashboard

📌 dashboard.html

{% extends "admin/base_site.html" %}
{% block content %}

<div class="container-fluid">
    <div class="row">
        <div class="col-md-4 col-12">
            <div class="card text-center">
                <h3>{{ ogrenci_sayisi }}</h3>
                <p>Öğrenci</p>
            </div>
        </div>

        <div class="col-md-4 col-12">
            <div class="card text-center">
                <h3>{{ ogretmen_sayisi }}</h3>
                <p>Öğretmen</p>
            </div>
        </div>
    </div>
</div>

<canvas id="chart"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
new Chart(document.getElementById("chart"), {
    type: 'pie',
    data: {
        labels: ['Öğrenci', 'Öğretmen'],
        datasets: [{
            data: [{{ ogrenci_sayisi }}, {{ ogretmen_sayisi }}]
        }]
    }
});
</script>

{% endblock %}

✔ Responsive
✔ Mobil uyumlu
✔ Modern kart tasarımı


🎯 Sonuç

Artık sistemimiz:

✅ Otomatik not ortalaması
✅ Excel import
✅ PDF karne
✅ Full dark mode
✅ Mobil uyumlu dashboard

Bu artık basit proje değil — Gerçek bir okul otomasyonu admin paneli oldu 🚀


Artık sistemi gerçek bir okul otomasyonuna dönüştürüyoruz.

Altyapı yine:
Tema → Django Jazzmin
Grafik → Chart.js


🔔 1️⃣ Devamsızlık Sistemi

📌 models.py

class Devamsizlik(models.Model):
    ogrenci = models.ForeignKey("Ogrenci", on_delete=models.CASCADE)
    tarih = models.DateField()
    durum = models.BooleanField(default=False)  # True = Geldi, False = Gelmedi
    aciklama = models.CharField(max_length=200, blank=True)

    def __str__(self):
        return f"{self.ogrenci} - {self.tarih}"

📌 Admin Ayarı

@admin.register(Devamsizlik)
class DevamsizlikAdmin(admin.ModelAdmin):
    list_display = ("ogrenci", "tarih", "durum")
    list_filter = ("tarih", "durum")
    search_fields = ("ogrenci__ad", "ogrenci__soyad")
    date_hierarchy = "tarih"

📌 Öğrenci Modeline Toplam Devamsızlık

def devamsizlik_sayisi(self):
    return self.devamsizlik_set.filter(durum=False).count()

Admin’de:

list_display = ("ad", "soyad", "devamsizlik_sayisi")

🎉 Artık her öğrencinin devamsızlık sayısı görünüyor.


📅 2️⃣ Ders Programı Takvimi

📌 models.py

class DersProgrami(models.Model):
    GUNLER = [
        ("Pzt", "Pazartesi"),
        ("Sal", "Salı"),
        ("Car", "Çarşamba"),
        ("Per", "Perşembe"),
        ("Cum", "Cuma"),
    ]

    sinif = models.ForeignKey("Sinif", on_delete=models.CASCADE)
    ders = models.ForeignKey("Ders", on_delete=models.CASCADE)
    ogretmen = models.ForeignKey("Ogretmen", on_delete=models.CASCADE)
    gun = models.CharField(max_length=3, choices=GUNLER)
    saat = models.TimeField()

    def __str__(self):
        return f"{self.sinif} - {self.ders}"

📌 Admin

@admin.register(DersProgrami)
class DersProgramiAdmin(admin.ModelAdmin):
    list_display = ("sinif", "ders", "ogretmen", "gun", "saat")
    list_filter = ("sinif", "gun")

📌 Takvim Görünümü (Dashboard)

İstersen FullCalendar ekleyebiliriz ama basit liste için:

<table class="table">
<tr>
<th>Gün</th><th>Ders</th><th>Saat</th>
</tr>
{% for ders in ders_programlari %}
<tr>
<td>{{ ders.gun }}</td>
<td>{{ ders.ders }}</td>
<td>{{ ders.saat }}</td>
</tr>
{% endfor %}
</table>

Mobil uyumlu olur.


📊 3️⃣ Sınıf Bazlı İstatistik Grafik

Amaç:

  • Her sınıfın ortalaması

  • Devamsızlık oranı


📌 View

from django.db.models import Avg, Count

def sinif_istatistik(request):
    veriler = Sinif.objects.annotate(
        ortalama=Avg("ogrenci__not__puan"),
        devamsizlik=Count("ogrenci__devamsizlik", filter=models.Q(ogrenci__devamsizlik__durum=False))
    )

    context = {
        "siniflar": veriler
    }
    return TemplateResponse(request, "admin/sinif_chart.html", context)

📌 Chart.js Grafik

<canvas id="sinifChart"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
new Chart(document.getElementById("sinifChart"), {
    type: 'bar',
    data: {
        labels: [{% for s in siniflar %}"{{ s.ad }}",{% endfor %}],
        datasets: [{
            label: 'Ortalama',
            data: [{% for s in siniflar %}{{ s.ortalama|default:0 }},{% endfor %}]
        }]
    }
});
</script>

🎉 Artık sınıf bazlı grafik var.


🔐 4️⃣ Öğretmen Sadece Kendi Öğrencilerini Görsün

Bu profesyonel bir özellik 👌


📌 Ogretmen Modeline User Bağlayalım

from django.contrib.auth.models import User

class Ogretmen(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ad = models.CharField(max_length=50)

📌 Öğrenci Modeline Öğretmen Alanı

class Ogrenci(models.Model):
    ogretmen = models.ForeignKey(Ogretmen, on_delete=models.CASCADE)

📌 Admin Filtreleme

class OgrenciAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        qs = super().get_queryset(request)

        if request.user.is_superuser:
            return qs

        try:
            ogretmen = Ogretmen.objects.get(user=request.user)
            return qs.filter(ogretmen=ogretmen)
        except Ogretmen.DoesNotExist:
            return qs.none()

🎯 Sonuç:

  • Müdür → Tüm öğrencileri görür

  • Öğretmen → Sadece kendi öğrencilerini görür


🚀 Artık Sistemimiz

✅ Devamsızlık takibi
✅ Ders programı
✅ Sınıf grafikleri
✅ Rol bazlı veri güvenliği
✅ Modern admin tasarımı

Bu artık gerçek bir mini MEB otomasyonu seviyesinde 🎓


Artık sistemi Admin panelinden çıkarıp gerçek okul otomasyonuna dönüştürüyoruz.

Altyapı yine:
Backend → Django
Grafik → Chart.js
SMS → Twilio (örnek servis)


📱 1️⃣ Öğrenci Giriş Paneli (Ayrı Frontend)

Amaç:

  • Öğrenci giriş yapacak

  • Notlarını görecek

  • Devamsızlık durumunu görecek

  • Rozetlerini görecek


📌 Öğrenciye User Bağlama

from django.contrib.auth.models import User

class Ogrenci(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ad = models.CharField(max_length=50)
    soyad = models.CharField(max_length=50)

📌 Login Sistemi (views.py)

from django.contrib.auth.decorators import login_required
from django.shortcuts import render

@login_required
def ogrenci_panel(request):
    ogrenci = request.user.ogrenci
    notlar = ogrenci.not_set.all()
    devamsizlik = ogrenci.devamsizlik_set.filter(durum=False).count()

    context = {
        "ogrenci": ogrenci,
        "notlar": notlar,
        "devamsizlik": devamsizlik,
        "ortalama": ogrenci.ortalama(),
    }
    return render(request, "ogrenci/panel.html", context)

📌 panel.html (Mobil Uyumlu)

<div class="container">
  <h2>Hoşgeldin {{ ogrenci.ad }}</h2>

  <div class="card">
      <h4>Ortalama: {{ ortalama }}</h4>
      <p>Devamsızlık: {{ devamsizlik }}</p>
  </div>

  <canvas id="notChart"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
new Chart(document.getElementById("notChart"), {
    type: 'bar',
    data: {
        labels: [{% for n in notlar %}"{{ n.ders.ad }}",{% endfor %}],
        datasets: [{
            label: 'Notlar',
            data: [{% for n in notlar %}{{ n.puan }},{% endfor %}]
        }]
    }
});
</script>

🎉 Artık öğrenci kendi paneline sahip.


📩 2️⃣ Veli SMS Bildirim Sistemi

Amaç:

  • Devamsızlık olunca veliye SMS

  • Ortalama düşünce SMS


📌 Ogrenci Modeline Veli Telefon

veli_tel = models.CharField(max_length=15)

📌 SMS Gönderme Fonksiyonu

from twilio.rest import Client

def sms_gonder(numara, mesaj):
    account_sid = "SID"
    auth_token = "TOKEN"
    client = Client(account_sid, auth_token)

    client.messages.create(
        body=mesaj,
        from_="+123456789",
        to=numara
    )

📌 Devamsızlık Kaydedilince Otomatik SMS

from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=Devamsizlik)
def devamsizlik_sms(sender, instance, created, **kwargs):
    if created and instance.durum == False:
        mesaj = f"{instance.ogrenci.ad} bugün okula gelmedi."
        sms_gonder(instance.ogrenci.veli_tel, mesaj)

🎯 Artık veliye otomatik SMS gider.


📊 3️⃣ Karne Ortalamasına Göre Başarı Rozetleri

📌 Model

class Rozet(models.Model):
    isim = models.CharField(max_length=50)
    min_ortalama = models.FloatField()

📌 Öğrenciye Rozet Atama

def rozet_hesapla(self):
    ort = self.ortalama()

    if ort >= 90:
        return "Altın Başarı"
    elif ort >= 75:
        return "Gümüş Başarı"
    elif ort >= 60:
        return "Bronz Başarı"
    else:
        return "Gelişim Gerekli"

Admin’de:

list_display = ("ad", "soyad", "ortalama", "rozet_hesapla")

Frontend’de rozet gösterilebilir:

<h3>Rozet: {{ ogrenci.rozet_hesapla }}</h3>

🔔 4️⃣ Otomatik Devamsızlık Uyarı Sistemi

Amaç:

  • 3 gün üst üste gelmeyen öğrenciye SMS

  • 5 gün devamsızlıkta müdüre bildirim


📌 Kontrol Fonksiyonu

def devamsizlik_kontrol(ogrenci):
    devamsizlik_sayisi = ogrenci.devamsizlik_set.filter(durum=False).count()

    if devamsizlik_sayisi >= 3:
        sms_gonder(ogrenci.veli_tel, "3 gün devamsızlık yapıldı!")

    if devamsizlik_sayisi >= 5:
        print("Müdüre bildirildi")

📌 Signal İçine Ekleyelim

@receiver(post_save, sender=Devamsizlik)
def kontrol(sender, instance, created, **kwargs):
    if created:
        devamsizlik_kontrol(instance.ogrenci)

🚀 Şu An Sistemimiz

✅ Öğrenci giriş paneli
✅ Mobil uyumlu not grafiği
✅ Veli SMS sistemi
✅ Başarı rozetleri
✅ Otomatik devamsızlık alarmı

Bu artık mini e-Okul sistemi seviyesinde 🎓


Yorumlar

Bu blogdaki popüler yayınlar

Pardus Üzerine Django Kurulumu

Python ile Web Geliştirme: Django App Oluşturma