giriiş
Bu eğitimde, depolayacağımız blog uygulama verilerinin alanlarını ve davranışlarını tanımlayan Django modelleri oluşturacağız. Bu modeller, Django uygulama verilerinizi veritabanına eşler. Django, Nesne İlişkisel Eşleme (ORM) API'si aracılığıyla veritabanı tabloları oluşturmak için bu modelleri kullanır ve bunlara "modeller" denir.
Ön koşullar
Bu eğitim Django Geliştirme serisinin bir parçasıdır ve bu serinin devamıdır.
Eğer bu seriyi takip etmiyorsanız, şu varsayımlarda bulunuyoruz:
- Django sürüm 4 veya üzerini yüklediniz.
- Django uygulamanızı bir veritabanına bağladınız.
- Unix tabanlı bir işletim sistemiyle çalışıyorsunuz, tercihen Ubuntu 22.04 bulut sunucusunu tercih edin, çünkü test ettiğimiz sistem bu.
Bu eğitim ağırlıklı olarak Django modelleriyle ilgili olduğundan, farklı bir kurulumunuz olsa bile takip edebilirsiniz.
Adım 1 – Django uygulamasını oluşturun
Django'nun modüler felsefesine bağlı kalarak, projemizde blog sitesini oluşturmak için gerekli tüm dosyaları içeren bir Django uygulaması oluşturacağız.
Python ve Django'da çalışmaya başladığımızda, Python sanal ortamımızı etkinleştirmemiz ve uygulamamızın kök dizinine taşımamız gerekir. Seriyi takip ettiyseniz, bunu aşağıdaki komutu yazarak yapabilirsiniz.
cd ~/my_blog_app
. env/bin/activate
cd blogr code... */Oradan şu komutu çalıştıralım:
python manage.py startapp blogsiteBu program blog sitemizi bir dizinle birlikte oluşturur.
Eğitim serisinin bu noktasında projeniz için aşağıdaki dizin yapısına sahip olacaksınız:
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.pyBu eğitimde odaklanacağımız dosya, sitenin blog dizininde bulunan models.py dosyası olacaktır.
Adım 2 – Gönderi Şablonları Ekleyin
Öncelikle, Post modeli oluşturmak için gerekli kodu içeren models.py dosyasını açıp düzenlememiz gerekiyor. Bir Post modeli aşağıdaki veritabanı alanlarını içerir:
- BAŞLIK – Blog yazısının başlığı.
- Slug – Web sayfalarına ait geçerli URL'lerin saklandığı ve oluşturulduğu yer.
- İÇERİK – Blog yazısının metinsel içeriği.
- create_on – Gönderinin oluşturulduğu tarih.
- YAZAR – Yazıyı yazan kişi.
Şimdi models.py dosyasının bulunduğu dizine gidin.
cd ~/my_blog_app/blog/blogsiteDosyanın içeriğini terminalinizde görüntülemek için cat komutunu kullanın.
cat models.pyDosya, modelleri içe aktaran aşağıdaki kodu ve bu models.py dosyasına nelerin girildiğini açıklayan bir yorumu içermelidir.
from django.db import models
# Create your models here.Favori metin düzenleyicinizi kullanarak models.py dosyasına aşağıdaki kodu ekleyin. Metin düzenleyicimiz olarak nano'yu kullanacağız, ancak siz istediğinizi kullanabilirsiniz.
nano models.pyBu dosyada, API modellerini içe aktarmak için kod zaten eklenmiş durumda, aşağıdaki yorumu kaldırabiliriz. Ardından, dizelerden slug'lar oluşturmak için slugify'ı, kimlik doğrulama için Django kullanıcısını ve URL oluşturmada bize daha fazla esneklik sağlamak için django.urls'den tersini içe aktaracağız.
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverseDaha sonra Post adını vereceğimiz model sınıfına, title, slug, content, created_on ve author veritabanı alanlarını içeren bir sınıf metodu ekleyin. Bunları içe aktarma ifadelerinizin altına ekleyin.
...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()Ardından, URL oluşturma ve gönderi kaydetme işlevi ekliyoruz. Bu çok önemli çünkü benzersiz gönderimize uygun benzersiz bir bağlantı oluşturuyor.
...
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)Şimdi modele gönderilerin web sayfasında nasıl sıralanıp görüntüleneceğini söylememiz gerekiyor. Bunun mantığı, iç içe geçmiş bir meta sınıfına eklenecek. Meta sınıfı genellikle veritabanı alan tanımıyla ilgili olmayan diğer önemli model mantığını içerir.
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.titleSon olarak, bu dosyaya Comment modelini ekliyoruz. Bu, imzasında models.Models bulunan Comment adlı başka bir sınıf eklemeyi ve aşağıdaki veritabanı alanlarını tanımlamayı içerir:
- İSİM – Yorumu gönderen kişinin adı.
- E-POSTA – Yorumu gönderen kişinin e-posta adresi.
- METİN – Yorumun kendi metni.
- POST – Yorumun yapıldığı gönderi.
- create_on – Yorumun oluşturulduğu zaman.
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)Bu noktada models.py tamamlanmış olacak. models.py dosyanızın aşağıdakilerle eşleştiğinden emin olun:
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)Dosyayı kaydedip kapattığınızdan emin olun. Nano kullanıyorsanız, bunu CTRL ve X'e, ardından Y'ye ve ardından ENTER'a basarak yapabilirsiniz.
models.py dosyası çalışırken settings.py dosyamızı güncelleyebiliriz.
Adım 3 – Ayarları Güncelleyin
Uygulamamıza modeller eklediğimize göre, projemize yeni eklediğimiz blog sitesi uygulamasının varlığını bildirmemiz gerekiyor. Bunu, uygulamayı settings.py dosyasının INSTALLED_APPS bölümüne ekleyerek yapıyoruz.
settings.py dosyanızın bulunduğu dizine gidin.
cd ~/my_blog_app/blog/blogBuradan örneğin nano ile settings.py dosyanızı açın.
nano settings.pyDosyayı açarak sitenizin blog uygulamasını aşağıda gösterildiği gibi dosyanın INSTALLED_APPS bölümüne ekleyin.
# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]Sitenin blog uygulaması eklendiğinde dosyayı kaydedip çıkabilirsiniz.
Bu noktada bu değişiklikleri hayata geçirmek için ilerlemeye hazırız.
Adım 4 – Göçü gerçekleştirin
Gönderi ve Yorum modelleri eklendikten sonraki adım, bu değişiklikleri uygulayarak MySQL veritabanı şemamızın bunları tanımasını ve gerekli tabloları oluşturmasını sağlamaktır.
Öncelikle, makemigrations komutunu kullanarak model değişikliklerimizi ayrı geçiş dosyalarına paketlememiz gerekiyor. Bu dosyalar, Git gibi bir sürüm kontrol sistemindeki commit'lere benzer.
Şimdi, ~/my_blog_app/blog/blogsite/migrations adresine gidip ls komutunu çalıştırırsanız, yalnızca bir __init__.py dosyası olduğunu fark edeceksiniz. Bu, göçleri eklediğimizde değişecek.
cd komutunu kullanarak blog dizinine şu şekilde geçin:
cd ~/my_blog_app/blogDaha sonra manager.py dosyasında makemigrations komutunu çalıştırın.
python manage.py makemigrationsDaha sonra terminal pencerenizde aşağıdaki çıktıyı almalısınız:
Output
Migrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment
/~/my_blog_app/blog/blogsite/migrations dizinine gittiğimizde yalnızca __init__.py dosyasının olduğunu hatırlıyor musunuz? Şimdi o dizine geri dönersek, iki öğenin daha eklendiğini göreceğiz: __pycache__ ve 0001_initial.py. 0001_initial.py dosyası, makemigrations'ı çalıştırdığımızda otomatik olarak oluşturuldu. Makemigrations'ı her çalıştırdığınızda benzer bir dosya oluşturulacaktır.
Dosyanın içeriğini okumak istiyorsanız, dosyanın bulunduğu dizinden 0001_initial.py'yi çalıştırmanız yeterli.
Şimdi ~/my_blog_app/blog adresine gidin:
cd ~/my_blog_app/blogBir geçiş dosyası oluşturduğumuza göre, bu dosyaların açıkladığı değişiklikleri migrate komutunu kullanarak veritabanına uygulamamız gerekiyor. Ancak önce, showmigrations komutunu kullanarak şu anda hangi geçişlerin mevcut olduğunu kontrol edelim.
python manage.py showmigrationsOutput
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
blogsite
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initialPost ve Comment modelleriyle oluşturduğumuz 0001_initial hariç tüm geçişlerin kontrol edildiğini göreceksiniz.
Şimdi, aşağıdaki komutu kullanarak geçişler tamamlandıktan sonra hangi SQL ifadelerinin çalıştırıldığını kontrol edelim. Bu komut, geçişi ve geçiş başlığını argüman olarak alır:
python manage.py sqlmigrate blogsite 0001_initialAşağıda sahne arkasında gerçekleştirilen gerçek SQL sorgusu gösterilmektedir.
Output
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);Şimdi göçleri çalıştırıp MySQL veritabanımıza uygulayalım.
python manage.py migrateAşağıdaki çıktıyı alacağız:
Output
Operations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OKGöçlerinizi başarıyla uyguladınız.
Django belgelerinde belirtildiği gibi, MySQL'i arka uç olarak kullanarak Django'yu taşımanın üç uyarısı olduğunu aklınızda bulundurmanız önemlidir.
- Şema değişikliği işlemleriyle ilgili işlemler desteklenmiyor. Başka bir deyişle, bir geçiş başarısız olursa, başka bir geçiş gerçekleştirmek için yaptığınız değişiklikleri manuel olarak seçmeniz gerekir. Başarısız geçişte herhangi bir değişiklik yapmadan önceki bir noktaya geri dönmenin bir yolu yoktur.
- Çoğu şema değişikliği işleminde MySQL, tabloları tamamen yeniden yazar. En kötü durumda, zaman karmaşıklığı, tabloya sütun eklenecek veya kaldırılacak satır sayısıyla orantılıdır. Django belgelerine göre, bu işlem her bir milyon satır için bir dakika kadar yavaş olabilir.
- MySQL'de sütun, tablo ve dizin adlarının uzunluğu konusunda küçük sınırlamalar vardır. Ayrıca, tüm sütun ve dizin birimlerinin toplam boyutu için de bir sınırlama vardır. Bazı diğer arka uçlar Django'da oluşturulan daha yüksek sınırları destekleyebilirken, aynı dizinler MySQL arka ucuyla oluşturulamaz.
Django ile kullanmayı düşündüğünüz herhangi bir veritabanı için her birinin avantajlarını ve dezavantajlarını tarttığınızdan emin olun.
Adım 5 – Veritabanı şemasını doğrulayın
Göç işlemi tamamlandıktan sonra Django modelleri aracılığıyla oluşturduğumuz MySQL tablolarının başarılı bir şekilde üretildiğini doğrulamamız gerekiyor.
Bunu yapmak için MySQL'e giriş yapmak üzere terminalde aşağıdaki komutu çalıştırın.
mysql blog_data -u djangouserŞimdi blog_data veritabanımızı seçin. Hangi veritabanını kullandığınızı bilmiyorsanız, SHOW DATABASES komutuyla tüm veritabanlarını gösterebilirsiniz. SQL'de
USE blog_data;Daha sonra tabloları görüntülemek için aşağıdaki komutu yazın.
SHOW TABLES;Bu SQL sorgusu aşağıdakileri ortaya çıkarmalıdır:
Output
+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.01 sec)Tablolar blogsite_comment ve blogsite_post'u içerir. Bunlar kendimiz oluşturduğumuz modellerdir. Tanımladığımız alanları içerdiklerini doğrulayalım.
DESCRIBE blogsite_comment;Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)DESCRIBE blogsite_post;Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)Django model geçişlerimizden veritabanı tablolarının başarıyla oluşturulduğunu doğruladık.
MySQL'i CTRL + D ile kapatabilir ve Python ortamınızdan çıkmaya hazır olduğunuzda disable komutunu çalıştırabilirsiniz:
deactivateGeliştirme ortamını devre dışı bırakmak sizi terminal komut satırına geri döndürür.
Sonuç
Bu eğitimde, bir blog web uygulamasına temel işlevler için modelleri başarıyla ekledik. Modelleri nasıl kodlayacağınızı, geçişlerin nasıl çalıştığını ve Django modellerini gerçek MySQL veritabanı tablolarına dönüştürme sürecini öğrendiniz.









