02 - Model Katmanı

April 04, 2018 5 minute read

Şimdi MTV’nin Model katmanına giriş yapacağız; ama bu konuya tek bir yazı yetmeyecek. Bu yazıyı okurken öğrendiklerinizi pekiştirmek için alıştırmaları yapmaya özen gösterirseniz, bir sonraki konuya daha kolay ısınırsınız.

Özet

  • Django’da uygulama oluşturacağız, bundle yapısına kısaca değineceğiz.
  • Model katmanını içerecek basit bir uygulama yazacağız.
  • Model migration script’leri oluşturacağız.
  • Bu yazıyla ilgili kodlara buradan erişebilirsiniz.

Oluştur, Oku, Güncelle, Sil

Veritabanında veri ile ilgili yapılabilecek dört temel işlemin baş harflerinden oluşuyor CRUD: Create - Read - Update - Delete. Her View katmanının belli bir amacı olur ve bu amaca göre Model katmanıyla bağlantıya geçer (bazen geçmez), sonucu Template katmanında gösterir. Django dökümantasyonunda çok güzel bir alıştırma1 var. Biz şimdi herhangi bir resim dosyasını analiz edip bir renk paleti oluşturmayı deneyeceğiz, önce modellemeden başlıyoruz. Önce uygulamayı oluşturalım:

# terminal
$ python manage.py startapp hello_palette

Bu noktada bundled application konusuna bir değinelim. Django’da her uygulamanın bir dizini var:

  • Bir Django projesi, birden fazla uygulamayı içinde barındırabilir.
  • Bir uygulama, birden fazla Django projesinde barınabilir.

Burada amaç, projenin belli bir işlevini veya özelliğini bir paket haline getirip, o paketi kolayca projeye kurup çıkarabilmek. pip2 ile kurulabilen her Django eklentisi aslında birer uygulamadır. Yani siz de geliştirdiğiniz bir uygulamayı, Template ve statik dosyalarını uygulama dizininde tutarak dağıtabilirsiniz.

Ben dağıtmayı düşünmediğim, bir projeye kökünden bağımlı olan uygulamalarımda iki şeye önem veriyorum:

  1. İsimlendirirken herhangi bir isim çakışmasını önlemek için proje adıyla bir prefix ekliyorum: palette yerine hello_palette gibi.
  2. templates ve static dosyalarımı uygulamanın içinde değil, ortak proje dizininde tutmayı tercih ediyorum.
# terminal
$ ls
hello_django/  hello_palette/  manage.py*  static/  templates/
# terminal
$ ls hello_palette/
__init__.py  admin.py  apps.py  migrations/  models.py  tests.py  views.py

Bir uygulama oluşturduğumuzda oluşan dosya ve dizin yapısı bu. Model katmanında ORM3 model objelerimizi models.py dosyasında tutacağız, Model katmanında yapılan değişiklikleri içeren, otomatik oluşturulan scriptleri migrations/ dizininde bulabileceğiz. Şimdi bir örnekle ORM konusuna girelim:

# models.py
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Palette(models.Model):
    image = models.ImageField(verbose_name=_("Image"), upload_to='images/')
    colors = models.TextField(verbose_name=_("Colors"))
    created_at = models.DateTimeField(verbose_name=_("Created at"), auto_now_add=True)

    class Meta:
        verbose_name = _("Palette")
        verbose_name_plural = _("Palettes")
        ordering = ('-created_at',)

    def __str__(self):
        return self.image.path

Bizim varsayılan veritabanımız SQLite ve daha ilk andan kullanıma hazır. Fakat veritabanımızda henüz Palette model objemiz ile ilgili bir table ve columnlar yok. Model katmanımızda yaptığımız her değişikliğin veritabanımıza yansıtılması için bir migration script oluşturmamız gerekiyor.

# terminal
$ python manage.py makemigrations hello_palette
App 'hello_palette' could not be found. Is it in INSTALLED_APPS?

Önemli bir şey unuttuk, uygulamayı kurmadan kullanmaya çalıştık. Yeni uygulamamızı INSTALLED_APPS listesine ekleyelim:

# settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'hello_palette',  # en sona, sira onemli.
]
...
# terminal
$ python manage.py makemigrations hello_palette
SystemCheckError: System check identified some issues:

ERRORS:
hello_palette.Palette.image: (fields.E210) Cannot use ImageField because Pillow is not installed.
        HINT: Get Pillow at https://pypi.python.org/pypi/Pillow or run command "pip install Pillow".

Bu sefer de eksik bağımlılık nedeniyle hata aldık. Bu sorunu nasıl çözeceğimize dair bir ipucu zaten verilmiş ama yeri gelmişken bağımlılıklar konusuna el atalım.

Proje Bağımlılıkları, requirements.txt

Projeye başlarken pip ile kurduğumuz ilk bağımlılığımızı hatırlayalım, Django. Şimdi resim dosyalarımız ile ilgili meta datayı veritabanında saklamak isterken Django bizden Pillow kurmamızı istedi. Projenin kapasitesi, özellikleri arttıkça bağımlılıklar artar. Bizim bunları her kurulumda tek tek kurmamız, sürümlerini kontrol etmemiz, yönetmemiz epey zor. Fakat bir requirements.txt dosyası oluşturup bu listeyi saklarsak, bu sorunu büyük ölçüde çözmüş oluruz:

# requirements.txt
Django==2.0.3
Pillow==5.1.0

Bağımlılıkların sürümünü PyPI sitesinden bakıp öğrenebilirsiniz. Bağımlılık dosyamızı hazırladıktan sonra paketleri artık bir komutla kurabiliriz:

# terminal
$ pip install -r requirements.txt
Requirement already satisfied: Django==2.0.3 in c:\users\gokmen\appdata\local\programs\python\python36-32\lib\site-packages (from -r requirements.txt (line 1))
Collecting Pillow==5.1.0 (from -r requirements.txt (line 2))
  Using cached Pillow-5.1.0-cp36-cp36m-win32.whl
Requirement already satisfied: pytz in c:\users\gokmen\appdata\local\programs\python\python36-32\lib\site-packages (from Django==2.0.3->-r requirements.txt (line 1))
Installing collected packages: Pillow
Successfully installed Pillow-5.1.0

Son kez migration script oluşturmayı deneyelim:

# terminal
$ python manage.py makemigrations hello_palette
Migrations for 'hello_palette':
  hello_palette\migrations\0001_initial.py
    - Create model Palette

Oldu! Elimizde veritabanında istediğimiz tabloları ve columnları oluşturacak bir script’imiz var. Artık sıra veritabanında4:

# terminal
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, hello_palette, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying hello_palette.0001_initial... OK  # bizimki burada.
  Applying sessions.0001_initial... OK

Hayda, bir migration script’imiz var sanıyorduk. Tabi ki öyle değil, auth, contenttypes, sessions… Bunların hepsi birer uygulama ve dikkat ederseniz bunlar INSTALLED_APPS listesinde de var. Projede kullandığımız uygulamaların veritabanımıza henüz kabul edilmemiş migration script’leri varsa, Django bunları tespit edip belli sırayla veritabanımıza uygular. Peki bir migration script’in uygulanıp uygulanmadığını Django nasıl anlıyor? O bilgiyi de veritabanında tutarak! Yani Django’daki migration uygulamasının da bir tablosu var.

Bir sonraki yazımda palette uygulamasını kodlamaya devam edeceğiz. Sağlıcakla.


  1. Ben kendi deneyimlerimi katarak bu yazı dizisini hazırlıyorum; ancak siz çok geç olmadan Django dökümantasyonuna elinizi, gözünüzü alıştırın. Bu yazıda öğrendiklerinizi buradan pekiştirmenizi tavsiye ediyorum. [return]
  2. Tüm Django paketlerini buradan görebilirsiniz. [return]
  3. Object-Relational Mapping kısaltması ORM’de temel amaç, kodumuzun içinde, kullandığımız programlama dilinin sağladığı kolaylıklardan sonuna kadar yararlanarak veritabanında çeşitli işlemler gerçekleştirmek. [return]
  4. Projeyi ilk oluşturduğumuzda bazı uygulamalar önceden kurulu geldiği için beklediğimizden fazla migration çalıştı. Bu uygulamaların bir çoğuna daha sonra tekrar değineceğiz. [return]