Tip İpuçları ile Django Ayarlarınızı Kolaylaştırın: Pydantic Eğitimi

Yayınlanan: 2022-07-22

Yeni ortamlar eklemek için sağlam ve ölçeklenebilir bir yoldan yoksun olduğum için eskiden Django projeleri beni hayal kırıklığına uğratırdı. Pydantic ve Python tipi ipuçlarını bir araya getirerek ihtiyacım olan güçlü temeli oluşturdum.

PEP 484'te açıklandığı gibi, tür ipuçları statik analizi destekler, ancak aynı ek açıklamalar çalışma zamanında da mevcuttur. Pydantic gibi üçüncü taraf paketleri, bu ek meta verileri kullanan çalışma zamanı türü denetimi sunar. Pydantic, ayarlar meta verilerini yönetmeye ve çalışma zamanı veri doğrulaması gerçekleştirmeye yardımcı olmak için Python türü ipuçlarını kullanır.

Bu pydantic öğreticisi, Django ile pydantic ayar yönetimini kullanmanın geniş kapsamlı, olumlu etkilerini gösterecektir.

Yapılandırmamız, Twelve-Factor App web sitesinde açıklanan en iyi uygulamalara bağlıdır:

  1. Sabit olmayan ve gizli konfigürasyonları ortam değişkenleri olarak tanımlayın.
  2. Geliştirme ortamlarında, bir .env dosyasında ortam değişkenlerini tanımlayın ve .gitignore dosyasını .env dosyasına ekleyin.
  3. KG, hazırlama ve üretim ortamları için ortam değişkenlerini (gizli) tanımlamak için bulut sağlayıcısının mekanizmalarını kullanın.
  4. Kendini ortam değişkenlerinden yapılandıran tek bir settings.py dosyası kullanın.
  5. Django konfigürasyonlarını tanımlayan Python değişkenleri üzerine ortam değişkenlerini okumak, kontrol etmek, doğrulamak ve yazmak için pydantic kullanın.

Alternatif olarak, bazı geliştiriciler settings_dev.py ve settings_prod.py gibi birden çok ayar dosyası oluşturur. Ne yazık ki, bu yaklaşım iyi ölçeklenmiyor. Kod tekrarına, kafa karışıklığına, bulunması zor hatalara ve daha yüksek bakım çabalarına yol açar.

Yukarıda belirtilen en iyi uygulamaları kullanarak, herhangi bir sayıda ortam eklemek kolay, iyi tanımlanmış ve hatasızdır. Daha karmaşık bir ortam yapılandırmasını keşfedebilsek de, netlik için iki tanesine odaklanacağız: geliştirme ve üretim.

Bu pratikte neye benziyor?

Pydantic Ayarları Yönetimi ve Ortam Değişkenleri

Şimdi hem geliştirme hem de üretimde bir örneğe odaklanıyoruz. Her ortamın ayarlarını nasıl farklı şekilde yapılandırdığını ve pydantic'in her birini nasıl desteklediğini gösteriyoruz.

Örnek uygulamamız Django destekli bir veritabanı gerektiriyor, bu yüzden veritabanı bağlantı dizesini saklamamız gerekiyor. Veritabanı bağlantı yapılandırma bilgilerini, dj-database-url Python paketini kullanarak DATABASE_URL adlı bir ortam değişkenine taşıyoruz. Lütfen bu değişkenin str türünde olduğunu ve aşağıdaki gibi biçimlendirildiğini unutmayın:

 postgres://{user}:{password}@{hostname}:{port}/{database-name} mysql://{user}:{password}@{hostname}:{port}/{database-name} oracle://{user}:{password}@{hostname}:{port}/{database-name} sqlite:///PATH

Geliştirme ortamımızda, kullanım kolaylığı için Docker içeren bir PostgreSQL örneği kullanabiliriz, üretim ortamımızda ise sağlanan bir veritabanı hizmetine işaret edeceğiz.

Tanımlamak istediğimiz başka bir değişken bir boolean, DEBUG . Django'daki DEBUG bayrağı, bir üretim dağıtımında asla açılmamalıdır. Geliştirme sırasında ek geri bildirim almak için tasarlanmıştır. Örneğin, hata ayıklama modunda, bir istisna oluştuğunda Django ayrıntılı hata sayfaları görüntüler.

Geliştirme ve üretim için farklı değerler şu şekilde tanımlanabilir:

Değişken ismi Gelişim Üretme
DATABASE_URL postgres://postgres:mypw@localhost:5432/mydb postgres://foo1:foo2@foo3:5432/foo4
DEBUG True False

Ortama bağlı olarak bu farklı ortam değişkeni değerlerini yönetmek için pydantic ayarları yönetim modülünü kullanıyoruz.

Hazırlık Adımları

Bunu uygulamaya koymak için, bu içerikle tek .env dosyamızı oluşturarak geliştirme ortamımızı yapılandırmaya başlıyoruz:

 DATABASE_URL=postgres://postgres:mypw@localhost:5432/mydb DEBUG=True

Ardından, .env dosyasını projenin .gitignore dosyasına ekliyoruz. .gitignore dosyası, kaynak denetiminde potansiyel olarak hassas bilgilerin kaydedilmesini önler.

Bu yaklaşım geliştirme ortamımızda iyi sonuç verirken, üretim ortamı belirtimimiz farklı bir mekanizma kullanır. En iyi uygulamalarımız, üretim ortamı değişkenlerinin ortam sırlarını kullanmasını zorunlu kılar. Örneğin, Heroku'da bu sırlara Config Vars adı verilir ve Heroku Panosu aracılığıyla yapılandırılır. Ortam değişkenleri olarak dağıtılan uygulamaya sunulurlar:

Config Vars web arayüzünün ekran görüntüsü. Sol kenar çubuğunda bir açıklama vardır: "Yapılandırma değişkenleri, uygulamanızın çalışma şeklini değiştirir. Kendi eklentilerinizi oluşturmanın yanı sıra, bazı eklentiler de kendi eklentileriyle birlikte gelir." Ana bölümde, her biri iki metin alanı, bir kalem simgesi ve bir X simgesi olan iki satır vardır. Metin alanları, önceki tablodaki "Değişken Adı" ve "Üretim" sütunlarıyla aynı verilere sahiptir. Sağ üst köşede "Config Vars'ı Gizle" yazan bir düğme bulunur.

Bundan sonra, bu değerleri her iki ortamdan da otomatik olarak okumak için uygulamanın yapılandırmasını ayarlamamız gerekiyor.

Django'nun settings.py yapılandırma

Örneğimiz için gerekli yapıyı sağlamak için yeni bir Django projesiyle başlayalım. Aşağıdaki terminal komutuyla yeni bir Django projesini destekliyoruz:

 $ django-admin startproject mysite

Artık mysite projesi için temel bir proje yapımız var. Projenin dosya yapısı aşağıdaki gibidir:

 mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py

settings.py dosyası, uygulama yapılandırmasını yönetmemizi sağlayan ortak kod içerir. İlgili ortama göre ayarlamamız gereken önceden tanımlanmış birçok varsayılan ayarı vardır.

Bu uygulama ayarlarını ortam değişkenleri ve pydantic kullanarak yönetmek için bu kodu settings.py dosyasının en üstüne ekleyin:

 import os from pathlib import Path from pydantic import ( BaseSettings, PostgresDsn, EmailStr, HttpUrl, ) import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent class SettingsFromEnvironment(BaseSettings): """Defines environment variables with their types and optional defaults""" DATABASE_URL: PostgresDsn DEBUG: bool = False class Config: """Defines configuration for pydantic environment loading""" env_file = str(BASE_DIR / ".env") case_sensitive = True config = SettingsFromEnvironment() os.environ["DATABASE_URL"] = config.DATABASE_URL DATABASES = { "default": dj_database_url.config(conn_max_age=600, ssl_require=True) } DEBUG = config.DEBUG

Bu kod şunları yapar:

  • pydantic'in BaseSettings sınıfından devralan SettingsFromEnvironment sınıfını tanımlar.
  • DATABASE_URL ve DEBUG tanımlar, türlerini ve isteğe bağlı varsayılanları Python türü ipuçlarını kullanarak ayarlar.
  • Sistemin ortam değişkenlerinde mevcut değilse, pydantic'e bir .env dosyasındaki değişkenleri aramasını söyleyen bir sınıf Config tanımlar.
  • Config sınıfını config nesnesinde başlatır; istenen değişkenler config.DATABASE_URL ve config.DEBUG olarak kullanılabilir hale gelir.
  • Bu config üyelerinden normal Django değişkenleri DATABASES ve DEBUG tanımlar.

Aynı kod tüm ortamlarda çalışır ve pydantic aşağıdakilerle ilgilenir:

  • DATABASE_URL ve DEBUG ortam değişkenlerini arar.
    • Üretimde olduğu gibi ortam değişkenleri olarak tanımlanırsa, bunları kullanır.
    • Aksi takdirde, bu değerleri .env dosyasından çeker.
    • Bir değer bulamazsa, aşağıdakileri yapacaktır:
      • DATABASE_URL için bir hata verir.
      • DEBUG için varsayılan bir False değeri atar.
  • Bir ortam değişkeni bulursa, alan türlerini kontrol eder ve bunlardan biri yanlışsa hata verir:
    • DATABASE_URL için, alan türünün PostgresDsn tarzı bir URL olduğunu doğrular.
    • DEBUG için, alan türünün geçerli, katı olmayan bir pydantic boole olduğunu doğrular.

Lütfen DATABASE_URL için yapılandırma değerinden işletim sisteminin ortam değişkeninin açık ayarına dikkat edin. DATABASE_URL zaten bir harici ortam değişkeni olarak tanımlandığından, os.environ["DATABASE_URL"] = config.DATABASE_URL değerini ayarlamak gereksiz görünebilir. Ancak bu, pydantic'in bu değişkeni ayrıştırmasına, kontrol etmesine ve doğrulamasına izin verir. DATABASE_URL ortam değişkeni eksikse veya yanlış biçimlendirilmişse, pydantic açık bir hata mesajı verecektir. Uygulama geliştirmeden sonraki ortamlara geçerken bu hata kontrolleri çok değerlidir.

Bir değişken tanımlı değilse, ya bir varsayılan atanacak ya da bir hata onun tanımlanmasını isteyecektir. Oluşturulan herhangi bir bilgi istemi, istenen değişken türünü de detaylandırır. Bu kontrollerin bir yan yararı, yeni ekip üyelerinin ve DevOps mühendislerinin hangi değişkenlerin tanımlanması gerektiğini daha kolay keşfetmesidir. Bu, uygulama tanımlanan tüm değişkenler olmadan çalıştığında ortaya çıkan bulunması zor sorunları önler.

Bu kadar. Uygulama artık, settings.py tek bir sürümünü kullanan, bakımı yapılabilir, ayar yönetimi uygulamasına sahiptir. Bu yaklaşımın güzelliği, bir .env dosyasında doğru ortam değişkenlerini veya barındırma ortamımız aracılığıyla mevcut olan herhangi bir başka istenen aracı belirlememize izin vermesidir.

Ölçeklenebilir Yol

Tüm Django projelerimde pydantic runtime yazarak Django ayarları yönetimini kullanıyorum. Daha küçük, daha sürdürülebilir kod tabanlarına yol açtığını buldum. Ayrıca yeni ortamlar eklemek için iyi yapılandırılmış, kendi kendini belgeleyen ve ölçeklenebilir bir yaklaşım sağlar.

Bu serideki bir sonraki makale, pydantic ayar yönetimi ile sıfırdan bir Django uygulaması oluşturmaya ve onu Heroku'ya dağıtmaya ilişkin adım adım bir eğitimdir.


Toptal Engineering Blog, bu makalede sunulan kod örneklerini gözden geçirdiği için Stephen Davidson'a şükranlarını sunar.

Bu makalenin önceki bir sürümü, belirli bir Python sürümünü vurguladı. Python birkaç yıldır tür ipuçlarını desteklediğinden, bu sürüm referansını kaldırarak giriş metnini genelleştirdik.