Professional Documents
Culture Documents
Two Scoops of Django 3.x by Daniel Audrey Feldroy (075-150) .En - TR
Two Scoops of Django 3.x by Daniel Audrey Feldroy (075-150) .En - TR
Two Scoops of Django 3.x by Daniel Audrey Feldroy (075-150) .En - TR
com
davranışlar.py başına model karışımlarını bulmak için bir seçenek Bölüm 6.7.1: Model Davranışlar
aka Mixins.
sabitler.py Uygulama düzeyinde ayarların yerleştirilmesi için iyi bir ad. Onlardan yeterince varsa
Bir uygulamaya dahil olmak, onları kendi modüllerine ayırmak bir projeye netlik
katabilir.
dekoratörler.py Dekoratörlerimizi bulmayı sevdiğimiz yer. Dekoratörler hakkında daha fazla bilgi için,
Bu bölümde listelenen tüm modüller için odak noktaları global araçlar değil 'uygulama düzeyinde' olmalıdır.
Global düzeydeki modüller şurada açıklanmıştır:Bölüm 31.1: Yardımcı Programlarınız için Bir Çekirdek
Uygulama Oluşturun.
Django'da kod yazarken, yeni başlayanların iş mantığının nereye gitmesi gerektiğini belirlemede
zorlanmaları yaygındır. Klasik örnek, birden çok model ve uygulamada kullanıcı nesneleri ve ilgili veriler
oluşturma sürecidir. Bizim durumumuzda Icecreamlandia temasına girmek için bir bilet
park:
1 Sistem, adı verilen bir yönetici yönteminde bir kullanıcı kaydı oluşturur. create_user()
3 oluştur() ayrıca arayarak bir bilet nesnesi oluşturur create_ticket() , adı verilen bir yönetici
4 oluştur_bilet() üçüncü taraf bir hizmet olan konuk Icecreamlandia check-in uygulamasına
bir API çağrısı yapar
Bu eylemler için tipik yerleşim, Kullanıcı ve Bilet'e atanan yöneticiler üzerindeki yöntemlere yayılır.
Diğerleri bunun yerine sınıf yöntemlerini kullanmayı tercih eder. Böylece şunları görebiliriz:
)
resize_avatar(avatar_url) Bilet.nesneler.
create_ticket(kullanıcı)dönüş kullanıcı
Bu işe yararken, hizmet katmanı yaklaşımı, kullanıcı nesnesi ve biletler arasında endişelerin
ayrılması gerektiğini savunuyor. Spesifik olarak, Bilet kodunu çağırmak için Kullanıcı koduna
gömme mantığı, iki etki alanını sıkı bir şekilde birleştirir. Böylece endişeleri ayrı tutmak için yeni
bir katman eklenir ve buna hizmet katmanı denir. Bu mimari için kod yerleştirilirservis.py ve
seçiciler.py.
├── api/
├── modeller.py
├── services.py # İş mantığı için hizmet katmanı konumu
├── seçiciler.py # Sorgular için hizmet katmanı konumu
├── testler/
# users/services.py'de
itibaren .modeller içe aktarmak kullanıcı
kullanıcı = kullanıcı(
e-posta=e-posta,
parola=parola,
avatar_url=avatar_url
)
kullanıcı.full_clean()
kullanıcı.yeniden boyutlandır_avatar()
kullanıcı.kaydetmek()
bilet = Bilet(kullanıcı=kullanıcı)
send_ticket_to_guest_checkin(bilet)dönüş
kullanıcı
Bu yaklaşımın avantajları:
a Bu yaklaşımla, döndürülen nesnelerin tür açıklamalarını eklemek, tipik olandan daha kolaydır.
Django
Bu yaklaşımın dezavantajları:
Hizmet katmanlarının daha fazla reddi veya geleneksel Django araçlarında iş mantığının nasıl organize
edileceğine ilişkin açıklamalar, uzun süredir Django sürdürücüsü James Bennett'in blogunda ve Django REST
a b-list.org/weblog/2020/mar/16/no-service/ b-list.org/weblog/2020/
a mar/23/still-no-service/ dabapps.com/blog/django-models-and-
a kapsülleme/
Two Scoops of Django'nun yazarları için hizmet katmanlarının kullanımı yeni değil - bunu
yıllardır görüyoruz. Temel Django uygulamalarından ayrılan herhangi bir teknikte olduğu gibi,
anekdotsal deneyimimiz, projelerin hizmet katmanlarını kullanarak biraz daha sık başarısız
olduğunu gördük. Bu, yaklaşımın değeri olmadığı anlamına gelmez, ancak ek soyutlama çabaya
değmeyebilir.
Bir projenin tüm kodu tek bir uygulamaya koyduğu yer burasıdır. Küçük Django projeleri için yaygın
olsa da, daha büyük projeler genellikle bu modeli izlemez.
Bu yaklaşımın olumlu yönleri var. Özellikle, geçişler daha kolaydır ve tablo adları
basitleştirilmiş bir model izler.
Tipik olarak, her şey dev bir şekilde bir araya toplanır. modeller.py, görünümler.py,
testler.py, ve urls.pymodüller. Sonunda ya proje kendi artan karmaşıklığı altında çöker ya
da dosyalar, modellerin kapsadığı alanlara dayalı olarak alt modüllere bölünür.
icecreamlandia projemizi kullanarak, "Kullanıcılar" ile ilgili her şeymodeller/users.py ve
"Biletler" modeller/tickets.py.
Dikkatli bir öngörüyle yapılırsa bunun işe yarayabileceğini lütfen unutmayın. Gerçekten de, Audrey
bunu bir projeyle büyük bir başarıya imza attı, beklenenden biraz daha fazla kod hokkabazlığı
içeriyordu. Bu, yalnızca bir Djangonaut birkaç başarılı Django projesini tamamladıktan sonra
keşfedilmesi gereken bir tekniktir.
James Beith, saygı duyduğumuz kıdemli bir mühendis. Bir Django projesinin nasıl yapılandırılacağı
konusunda ilginç bir görüşü var. James, tasarımında Django için ortak kalıpları açıkça yeniden
yazıyor. Onun için çalışıyor gibi görünse de, projedeki herhangi bir yeni geliştiricinin yeni bir
paradigma öğrenmesi gerektiğinden, sürdürülmesi daha zor bir proje yapar. Django'nun cazibesi,
bozmaktadır. Yeni bir şeyler deneme arzusunu selamlarken, Django projelerini yeniden tasarlama
4.6 Özet
Bu bölüm, Django uygulama tasarımı sanatını ele aldı. Spesifik olarak, her Django uygulaması sıkı bir
şekilde kendi görevine odaklanmalı ve basit, hatırlaması kolay bir isme sahip olmalıdır. Bir uygulama
çok karmaşık görünüyorsa, daha küçük uygulamalara bölünmelidir. Uygulama tasarımını doğru
yapmak pratik ve çaba gerektirir, ancak bu çabaya değer.
Ayrıca mimari uygulamalara alternatif yaklaşımları ve bunların içinde mantığın nasıl çağrıldığını da ele aldık.
Django 3, çoğu varsayılan değerlerle gelen ayarlar modülünde kontrol edilebilen 150'den fazla
ayara sahiptir. Ayarlar, sunucunuz başlatıldığında yüklenir ve deneyimli Django geliştiricileri,
sunucunun yeniden başlatılmasını gerektirdiğinden, üretimde ayarları değiştirmeye çalışmaktan
uzak durur.
Şekil 5.1: Projeniz büyüdükçe Django ayarlarınız oldukça karmaşık hale gelebilir.
a Tüm ayar dosyalarının sürüm kontrollü olması gerekir. Bu özellikle üretimde geçerlidir
tarih, saat ve ayar değişikliği açıklamalarının mutlaka takip edilmesi gereken
ortamlardır.
a Kendinizi Tekrar Etmeyin. yerine bir temel ayarlar dosyasından devralmalısınız.
bir dosyadan diğerine kesme ve yapıştırma.
a Gizli anahtarları güvende tutun. Versiyon kontrolünün dışında tutulmalıdırlar.
Geliştiriciler olarak, hazırlama veya üretim sunucuları devre dışı bırakılması (ve genellikle
yüklenmemesi) gereken hata ayıklama araçlarına ilişkin ayarlar gibi geliştirme için kendi gerekli
ayarlarımıza sahibiz.
Ayrıca, belirli ayarları genel veya özel kod havuzlarından uzak tutmak için genellikle iyi
nedenler vardır. NSGİZLİ ANAHTAR ayarı akla gelen ilk şeydir, ancak Amazon, Stripe ve diğer
parola türü değişkenler gibi hizmetlere yönelik API anahtarı ayarlarının korunması gerekir.
en iyi şekilde uzak tutulan benzersiz, öngörülemeyen bir ayara ayarlanması gerekir. Django'yu
bilinen bir programla çalıştırmaGİZLİ ANAHTAR Django'nun güvenlik korumalarının çoğunu yenerek
ciddi güvenlik açıklarına yol açabilir. Daha fazla ayrıntı için, okuyun
docs.djangoproject.com/en/3.2/topics/signing/.
için aynı uyarı GİZLİ ANAHTAR aynı zamanda üretim veritabanı parolaları, AWS anahtarları,
OAuth belirteçleri veya projenizin çalışması için ihtiyaç duyduğu diğer hassas veriler için de
geçerlidir.
Ortak bir çözüm oluşturmaktır local_settings.py sunucu veya geliştirme makinesi başına yerel
olarak oluşturulan ve kasıtlı olarak sürüm kontrolünün dışında tutulan modüller. Geliştiriciler
artık, sürüm kontrolünde kod izlenmeden iş mantığının dahil edilmesi de dahil olmak üzere,
geliştirmeye özel ayar değişiklikleri yapıyor. Hazırlama ve dağıtım sunucuları, sürüm
kontrolünde izlenmeden konuma özgü ayarlara ve mantığa sahip olabilir.
Ah...
a Herkes aynı şeyi kopyalar/yapıştırır local_settings.py modül her yerde Bu bir viyo-
Kendini Tekrar Etme ama daha büyük ölçekte mi?
Farklı bir yaklaşım benimseyelim. Geliştirme, hazırlama, test ve üretim ayarlarını, sürüm
kontrolü tarafından izlenen bir ayar dosyasındaki ortak bir temel nesneden devralan ayrı
bileşenlere ayıralım. Ayrıca, bunu sunucu sırlarının gizli kalacağı şekilde yaptığımızdan
emin olacağız.
birine sahip olmak yerine ayarlar.py dosya, bu kurulumla bir ayarlar/ ayar
dosyalarınızı içeren dizin. Bu dizin tipik olarak aşağıdakine benzer bir şey içerir:
ayarlar/
├── __init__.py
├── base.py
├── local.py
├── hazırlama.py
├── test.py
├── üretim.py
Python etkileşimli yorumlayıcısını Django ile başlatmak için, settings/local.py ayarlar dosyası:
Virtualenvwrapper hakkında daha kapsamlı bir anlayışa sahip olanlar için, bir-
diğer alternatif ayarlamaktır DJANGO_SETTINGS_MODULE ve PİTONPATH içinde
sonradan etkinleştirmek komut dosyası ve onları sonradan devre dışı bırakmak senaryo.
Ardından, sanalenv etkinleştirildiğinde, sadece yazabilirsiniz.piton herhangi bir
yerden ve bu değerleri projenize aktarın. Bu aynı zamanda yazarakdjango-admin
komut satırında -- olmadan çalışırayarlar seçenek.
HATA AYIKLAMA = NS
EMAIL_BACKEND = 'Django.core.mail.backends.console.EmailBackend'
VERİTABANLARI = {
'varsayılan': {
'MOTOR': 'Django.db.backends.postgresql','iki kaşık
'İSİM': toz',
'EV SAHİBİ': 'yerel ana bilgisayar',
}
}
INSTALLED_APPS += ['debug_toolbar', ]
Yine de başka bir avantaj daha var: Artık yok'eğer hata ayıklama' veya 'DEBUG değilse' projeler arasında
kopyalama/yapıştırma mantığı. Ayarlar artık çok daha basit!
Bu noktada, Django ayar dosyalarının kullanılmasını savunduğumuz tek, ıssız yer olduğunu
belirtmek isteriz. içe aktarmak *. Bunun nedeni Django ayar modüllerinin tekil durumu için
tüm ad alanını geçersiz kılmak istiyoruz.
Herkesin aynı ayarları özelleştirmesine güvenmektense, bu ayarları sürüm kontrolünde izlemek daha iyidir.
yerel.py kendi zevklerine göre modül. Bunu yapmanın güzel bir yolu, birden çok geliştirme ayarı dosyası
# settings/local_pydanny.pyitibaren
.yerel içe aktarmak *
Niye ya? Sadece kendi ayar dosyalarınızı sürüm kontrolünde tutmak değil, aynı zamanda takım
arkadaşlarınızın geliştirme ayarları dosyalarını görebilmek de iyidir. Bu şekilde, birinin yerel geliştirme
kurulumunda hayati veya yararlı bir ayarın eksik olup olmadığını anlayabilir ve herkesin yerel ayar
dosyalarının senkronize edildiğinden emin olabilirsiniz. Projelerimizin ayar düzeni için sıklıkla
kullandıkları şey:
ayarlar/
__init__.py
base.py
local_audreyr.py
local_pydanny.py
yerel.py
staging.py
test.py
üretim.py
Bunu çözmek için cevabımız kullanmaktır. Ortam Değişkenleri aramayı sevdiğimiz bir düzende,
peki,Ortam Değişkenleri Modeli.
Django (ve Python) tarafından desteklenen her işletim sistemi, ortam değişkenleri oluşturmak
için kolay yetenek sağlar.
a Sırları ayarların dışında tutmak, her ayar dosyasını sürüm kontrolünde saklamanıza olanak tanır
tereddüt etmeden. Tüm Python kodunuz, ayarlarınız da dahil olmak üzere gerçekten sürüm
kontrolünde saklanmalıdır.
a Her geliştiricinin kolayca güncelliğini yitirmiş, kopyalayıp yapıştırılmış bir sürümünü sürdürmesi yerine
5.3.1 Sırlar için Ortam Değişkenlerini Kullanmadan Önce Dikkat Edilmesi Gerekenler
Hedef üretim ortamınız Apache kullanıyorsa (Elastic Beanstalk dışında), işletim sistemi
ortam değişkenlerini aşağıda açıklandığı gibi ayarlamanın işe yaramadığını
keşfedeceksiniz. Sorunun kafa karıştırıcı olması, Apache'nin kendi ortam değişken
sistemine sahip olmasıdır, bu da neredeyse ihtiyacınız olan şey değildir.
Apache kullanıyorsanız ve local_settings anti-pattern'den kaçınmak istiyorsanız,
okumanızı öneririz. Bölüm 5.4: Ortam Değişkenlerini Kullanamadığınızda bu bölümde
daha sonra.
Catalina öncesi Mac ve kullanan birçok Linux dağıtımında bash kabuk için, bir satırın sonuna
aşağıdaki gibi satırlar eklenebilir. .bashrc, .bash_profile, veya .profil. Catalina ve sonrasındaki
Mac'ler.zshrc. Aynı API'yi kullanan ancak farklı anahtarlarla birden fazla projeyle uğraşırken,
bunları sanalenv'lerinizin sonuna da yerleştirebilirsiniz.bin/sonraki etkinleştirsenaryo:
ihracat SOME_SECRET_KEY=1c3-cr3am-15-nefisAUDREY_FREEZER_KEY=y34h-
ihracat r1ght-d0nt-t0uch-my-1c3-cr34m
Windows sistemlerinde, biraz daha zor. Bunları komut satırında tek tek ayarlayabilirsiniz (
cmd.exe) ile kalıcı bir şekilde setx ancak etkin olmaları için komut isteminizi kapatıp
yeniden açmanız gerekir. Bu komutları virtualenv'lerin sonuna yerleştirmek daha iyi bir
yoldur.bin/postactivate.bat komut dosyası etkinleştirildikten sonra kullanılabilirler:
Güç kalkanı varsayılan Windows kabuğundan çok daha güçlüdür ve Windows Vista ve
üzeri ile birlikte gelir. PowerShell kullanırken ortam değişkenlerini ayarlama:
Makine çapında:
Yukarıda listelenen komutlar aracılığıyla bir ortam değişkeni ayarladığınızda, ayarlanana veya
kabuk sona erene kadar bu terminal kabuğunda varlığını sürdürecektir. Bu, bir virtualenv'i devre
dışı bıraksanız bile ortam değişkeninin kaldığı anlamına gelir. Tecrübelerimize göre, bu zamanın
%99'unda iyidir. Ancak, ortam değişkenlerini sıkı bir şekilde kontrol etmek istediğimiz durumlar
vardır. Bunu yapmak için işletim sistemi veya kabuk varyantı için uygun komutu yürütürüz:
ayarsız SOME_SECRET_KEY
ayarsız AUDREY_FREEZER_KEY
Django projeniz Heroku, Python Anywhere, platform.sh vb. gibi bir hizmet olarak
platform (PaaS) aracılığıyla dağıtılıyorsa, belirli talimatlar için belgelere bakın.
Python tarafından ortam değişkenlerine nasıl eriştiğinizi görmek için yeni bir Python istemi açın
ve şunu yazın:
Ayar dosyalarınızdan birinden ortam değişkenlerine erişmek için şöyle bir şey
yapabilirsiniz:
işletim sistemi
Bu kalıbı takip etmek, tüm kodların sürüm kontrolünde kalabileceği ve tüm sırların güvende kalacağı anlamına gelir.
Yukarıdaki uygulamada, eğer GİZLİ ANAHTAR mevcut değil, bir Anahtar Hatası ,projeye
başlamayı imkansız hale getiriyor. Bu harika, ama birAnahtar Hatası aslında neyin yanlış
olduğu hakkında pek bir şey söylemez. Daha yararlı bir hata mesajı olmadan, özellikle
kullanıcılar beklerken ve dondurmanız erirken sunuculara dağıtma baskısı altında bu hata
ayıklamak zor olabilir.
# settings/base.py
içe aktarmak işletim sistemi
tanım get_env_variable(var_name):
"""Ortam değişkenini alın veya istisnayı döndürün."""denemek:
Ardından, ayar dosyalarınızdan herhangi birinde ortam değişkenlerinden gizli anahtarları aşağıdaki gibi
yükleyebilirsiniz:
SOME_SECRET_KEY = get_env_variable('SOME_SECRET_KEY')
Şimdi, eğer yoksa SOME_SECRET_KEY bir ortam değişkeni olarak ayarladığınızda, aşağıdaki gibi faydalı
bir hata mesajıyla biten bir geri izleme elde edersiniz:
django.çekirdek.istisnalar.Yanlış Yapılandırılmış:
↪
→ SOME_SECRET_KEY
Çevre değişkeni.
Bir dizi üçüncü taraf paketi bizim fikrimizi alır. get_env_variable() varsayılanlar ve türler ve
destekleme gibi özellikler dahil olmak üzere işlev ve genişletme .ortamDosyalar.
Dezavantajı, herhangi bir karmaşık pakette elde ettiğinizle aynıdır: bazen uç durumlar
sorunlara neden olur. Bununla birlikte, çoğu oldukça kullanışlıdır ve favorilerimizden
bazılarını listeledik:
a github.com/joke2k/django-environ (Cookieecutter Django'da kullanılır)
a github.com/jazzband/django-configurations
1 JSON, .env, Config, YAML ve hatta XML olsun, tercih ettiğiniz yapılandırma biçimini kullanarak bir gizli
2 Gizli dizileri uyumlu ve açık bir şekilde yönetmek için bir gizli dizi yükleyici (aşağıda JSON
destekli örnek) ekleyin.
3 Gizli dosya adını projenin .gitignore dosya.
Tercihimiz sığ JSON dosyalarını kullanmaktır. JSON formatı, hem Python hem de Python dışı araçlar için
tercih edilen bir format olma avantajına sahiptir. Bunu yapmak için önce birsırlar.jsondosya:
{
"DOSYA ADI": "gizler.json","GİZLİ ANAHTAR":
"Bir sırrım var!","VERİTABANLARI_HOST":
"127.0.0.1","LİMAN": "5432"
kullanmak için sırlar.json dosya, temel ayarlar modülünüze aşağıdaki kodu ekleyin.
# settings/base.py
içe aktarmak json
dönüş sırlar[ayar]hariç
Anahtar Hatası:
hata_msg = 'Yı kur {0} Çevre
↪
→ değişken'.biçim(ayar)artırmak Yanlış
Yapılandırılmış(error_msg)
AWS Lambda'ya dağıtım için Zappa'yı tercih etmemizin nedenlerinden biri, ortam değişkeni
yönetimi için sunduğu farklı ve güçlü seçeneklerdir. Kesinlikle bir göz atmaya değer ve diğer
araçların ve barındırma platformlarının benimsemesini görmek istediğimiz bir şey.
Referans: github.com/Miserlou/Zappa#setting-environment-variables
Biz sığ JSON'un zorunlu basitliğini tercih ederken, diğerleri diğer dosya biçimlerini
tercih edebilir. Ek oluşturmayı okuyucuya bırakacağız.get_secret() bu formatlarla çalışan
alternatifler. Sadece gibi şeylere aşina olmayı unutmayınyaml.safe_load()
ve XML bombaları. GörmekBölüm 28.10: Python Kod Enjeksiyon Saldırılarına Karşı Savunma.
Jeff Triplett tarafından bize önerilen bu kalıbı takip etmek için önce bir
Gereksinimler/ içindeki dizin <depo_kök>. Sonra oluştur'.txt' ayarlar dizininizin
içeriğiyle eşleşen dosyalar. Sonuçlar şöyle görünmelidir:
Gereksinimler/
├── base.txt
├── local.txt
├── hazırlama.txt
├── üretim.txt
Django==3.2.0
psycopg2-ikili==2.8.8
djangorest çerçevesi==3.11.0
Sizin yerel.txt dosyası, yerel geliştirme için kullanılan bağımlılıklara sahip olmalıdır, örneğin:
kapsam==5.1
django-debug-araç çubuğu==2.2
kapsam==5.1
Prodüksiyon için:
Okuyucuya, Django ayar dosyalarındaki dosya yollarını asla sabit kodlamaması için alçakgönüllülükle yalvarıyoruz. Bugerçekten
kötü:
# settings/base.py
# MEDIA_ROOT'u Yapılandırma
#BUNU YAPMA! Yalnızca bir kullanıcının tercihlerine göre kodlanmış
MEDYA_KÖK = '/Users/pydanny/twoscoops_project/media'
# STATIC_ROOT'u yapılandırma
#BUNU YAPMA! Yalnızca bir kullanıcının tercihlerine göre kodlanmışSTATIC_ROOT = '/
Users/pydanny/twoscoops_project/collected_static'
# STATICFILES_DIRS yapılandırması
#BUNU YAPMA! Yalnızca bir kullanıcının tercihlerine göre kodlanmışSTATICFILES_DIRS
= ['/Users/pydanny/twoscoops_project/statik']
# ŞABLONLARI Yapılandırma
#BUNU YAPMA! Yalnızca bir kullanıcının tercihlerine göre kodlanmış
ŞABLONLAR = [
{
'GERİ UÇ':
↪
→ 'Django.template.backends.django.DjangoTemplates', DIRS: ['/Users/
pydanny/twoscoops_project/şablonlar',]
},
]
Yukarıdaki kod, adı verilen yaygın bir tuzağı temsil eder. sabit kodlama. Adı verilen
yukarıdaki kodsabit yol, kötü çünkü bildiğiniz kadarıyla, pirzola (Daniel Feldroy),
bilgisayarını bu yol yapısına uyacak şekilde kuran tek kişidir. Bu örneği kullanmaya çalışan
herhangi biri, proje kesintilerini görecek ve onları dizin yapılarını değiştirmeye (olası değil)
veya ayarlar modülünü tercihlerine uyacak şekilde değiştirmeye zorlayacaktır (pydanny
dahil herkes için sorunlara neden olur).
Yol sorununu çözmek için, sezgisel olarak adlandırılmış bir proje kök değişkenini dinamik olarak belirledik BASE_DIR
temel ayarlar modülünün en üstünde. Dan beriBASE_DIR base.py'nin konumu ile ilgili olarak belirlenir,
projeniz herhangi bir geliştirme bilgisayarı veya sunucusundaki herhangi bir yerden çalıştırılabilir.
ayarlamanın en temiz yolunu buluyoruz. BASE_DIR-ayar ile olduğu gibi Pathlib, zarif, temiz yol
hesaplamaları yapan 3.4'ten beri Python'un bir parçası:
{
'GERİ UÇ':
↪
→ 'Django.template.backends.django.DjangoTemplates','DIRS':
[BASE_DIR / 'şablonlar']
},
]
gerçekten ayarlamak istiyorsanız BASE_DIR Python standart kitaplığı ile os.path kütüphane
olsa da, bu, yolları hesaba katacak şekilde yapmanın bir yoludur:
tanım kök(*dizinler):
base_dir = birleş(dirname(__dosya__), '..', '..')dönüş
abspath(join(base_dir, *yön))
BASE_DIR = kök()
MEDIA_ROOT = kök('medya')
STATIC_ROOT = kök('statik_kök')
STATICFILES_DIRS = [kök('statik')]
ŞABLONLAR = [
{
'GERİ UÇ':
↪
→ 'Django.template.backends.django.DjangoTemplates','DIRS': [kök(
'şablonlar')],
},
]
Bağlı olarak çeşitli yol ayarlarınızla BASE_DIR, dosya yolu ayarlarınızın çalışması gerekir, bu da
şablonlarınızın ve medyanızın hatasız yüklenmesi gerektiği anlamına gelir.
5.7 Özet
Parolalar ve API anahtarları dışındaki her şeyin sürüm kontrolünde izlenmesi gerektiğini
unutmayın.
Gerçek bir canlı prodüksiyon sunucusuna yönelik herhangi bir proje, birden çok ayar ve gereksinim
dosyasına ihtiyaç duyar. Django'ya yeni başlayanlar bile, projeleri orijinal geliştirme makinesinden
ayrılmaya hazır olduğunda bu tür ayarlar/gereksinim dosyası kurulumuna ihtiyaç duyar. Hem yeni
başlayan hem de ileri düzey geliştiriciler için iyi çalıştığından, çözümümüzün yanı sıra Apache dostu bir
çözüm sunuyoruz.
Ayrıca, sağlananlardan farklı bir kabuk tercih ederseniz, ortam değişkenleri çalışmaya devam eder.
Bunları tanımlamak için sözdizimini bilmeniz yeterlidir.
Çoğu zaman biz geliştiriciler, yaptığımız şeyin sonuçlarını düşünmeden model eklemeye veya
model değiştirmeye koşarız. Kod tabanımıza attığımız hızlı düzeltme veya özensiz "geçici"
tasarım kararı, önümüzdeki aylarda veya yıllarda bize zarar verebilir, çılgın geçici çözümlere
zorlayabilir veya mevcut verileri bozabilir.
Bu nedenle, Django'ya yeni modeller eklerken veya mevcut olanları değiştirirken bunu aklınızda bulundurun.
Bir şeyleri düşünmek için zaman ayırın ve temelinizi mümkün olduğunca güçlü ve sağlam olacak şekilde
tasarlayın.
İşte hemen hemen her projede kullandığımız modelle ilgili Django paketlerinin
hızlı bir listesi.
a django-model-utils gibi ortak kalıpları işlemek için Zaman DamgalıModel.
Tek bir uygulamada 20'den fazla model varsa, bunu daha küçük uygulamalara ayırmanın yollarını düşünün,
çünkü bu muhtemelen uygulamanızın çok fazla şey yaptığı anlamına gelir. Pratikte, bu sayıyı uygulama başına
Django'da model kalıtımı zor bir konudur. Django, model kalıtımı yapmanın üç yolunu
sunar:soyut temel sınıflar, çok tablolu kalıtım, ve proxy modelleri.
İşte üç model kalıtım stilinin artıları ve eksileri. Tam bir karşılaştırma yapmak için,
başlangıç olarak model kalıtımı kullanma seçeneğini de ekledik:
Hangi tür kalıtımın ne zaman kullanılacağını bilmek için bazı basit kurallar:
a Modeller arasındaki örtüşme minimum ise (örneğin, yalnızca birkaç modeliniz varsa)
bir veya iki aynı adlandırılmış alanı paylaşan), model mirasına gerek olmayabilir.
Sadece alanları her iki modele de ekleyin.
a Modellerin tekrarlanan alanlarının bakımını yapan modeller arasında yeterli örtüşme varsa
karışıklığa ve kasıtsız hatalara neden olursa, çoğu durumda ortak alanların soyut bir
temel modelde olması için kodun yeniden düzenlenmesi gerekir.
a Proxy modelleri ara sıra yararlı bir kolaylık özelliğidir, ancak çok farklıdırlar.
diğer iki model miras stilinden.
a Ne pahasına olursa olsun, herkes çok tablolu mirastan kaçınmalıdır (yukarıdaki uyarıya bakın), çünkü
hem kafa karışıklığı hem de önemli miktarda ek yük ekler. Çok tablolu devralma yerine açık
kullanınOneToOneFields ve Yabancı anahtarlar modeller arasında, böylece birleşimlerin ne zaman
geçildiğini kontrol edebilirsiniz. 20 yılı aşkın süredir Django yaparken çok tablolu kalıtımın
beladan başka bir şeye neden olduğunu hiç görmedik.
yaratıldı = modeller.DateTimeField(auto_now_add=NS)
değiştirilmiş = modeller.DateTimeField(auto_now=NS)
sınıf Meta:
Öz = NS
Örneğimizi soyut bir temel sınıfa dönüştüren örnekteki son iki satırı dikkatlice not
edin:
sınıf Meta:
Öz = NS
tanımlayarak Zaman DamgalıModel soyut bir temel sınıf olarak, ondan miras alan yeni
bir sınıf tanımladığımızda, Django bir core_timestampedmodel masa ne zaman göç
çalıştırılır.
# tatlar/models.py
itibaren django.db içe aktarmak modeller
Bu yalnızca bir tablo oluşturur: tatlar_flavor veritabanı tablosu. Tam olarak istediğimiz davranış
buydu.
Öte yandan, eğer Zaman DamgalıModel soyut bir temel sınıf değildi (yani, çok tablolu
kalıtım yoluyla somut bir temel sınıf), aynı zamanda bir core_timestampedmodel
tablo. Sadece bu değil, tüm alt sınıfları da dahil olmak üzereLezzet alanlardan yoksun olurdu ve örtük
yabancı anahtarlara geri dönerdi Zaman DamgalıModel sadece işlemek için oluşturuldu/değiştirildi
zaman damgaları. herhangi bir referansLezzet okuyan veya yazan Zaman DamgalıModel
iki tabloyu etkiler. (Şükürler olsun ki soyut!)
Unutmayın, somut mirasın kötü bir performans darboğazı olma potansiyeli vardır. Bu,
somut bir model sınıfını birden çok kez alt sınıfladığınızda daha da doğrudur.
a docs.djangoproject.com/en/3.2/topics/db/models/
# model kalıtımı
değişiklikleri tahmin edemez. İşte o zaman, geçişleri çalıştırmaya yardımcı olmak için python veya özel
SQL yazmayı araştırmak yararlıdır. Üretime giren herhangi bir projenin bir noktasında, ikisinden birini
kullanmak için bir neden bulacaksınız.RunPython veya RunSQL sınıflar:
a docs.djangoproject.com/en/3.2/ref/migration-operations/
# runpython
a docs.djangoproject.com/en/3.2/ref/migration-operations/#runsql
Değeri ne olursa olsun, tercihimiz kullanmaktır. RunPython önce RunSQL, ama güçlü yönlerinizin olduğu
yerde kalmanızı tavsiye ederiz.
Görmek: docs.djangoproject.com/en/3.2/topics/migrations/#model-managers
docs.djangoproject.com/en/3.2/topics/migrations/#historical-models
çağrıldıklarında bunlar çağrılmaz. Kendinizi uyarılmış düşünün, bu yıkıcı bir sonuç olabilir.
Ters geçişlerin çalışması için RunPython'a bir ters_kod callable kodunun etkilerini
geri almak için callable. Ancak, yazdığımız kod çağrılarının bazıları önemsizdir.
Örneğin, mevcut verileri yeni eklenen bir alanda birleştirirler. Bir ... Yazmak
ters_kod Bu işlevler için callable seçeneği ya imkansız ya da anlamsızdır. Bu
olduğunda, kullanınRunPython.noop olarak ters_kod .
Örneğin “Cone” adında yeni bir model oluşturduğumuzu varsayalım. Mevcut tüm
kepçelerin kendi konilerine ihtiyacı var, bu yüzden bir yazıyoruz.add_cones veri tabanına
koni ekleme işlevi. Ancak, geçişi tersine çevirirken, konileri kaldırmak için kod yazmak
anlamsızdır;göçler.Model Oluştur.database_backwards coni.cone tablosunu ve tüm
kayıtlarını bizim için silecektir. Bu nedenle, kullanmalıyızRunPython.noop için ters_kod :
sınıf Göç(göçler.Göç):
ilk = NS
bağımlılıklar =[
('kepçe', '0051_auto_20670724'),
]
operasyonlar = [
göçler.Model Oluştur(
isim='Koni',
alanlar=[
('İD', modeller.AutoField(auto_created=NS,
↪
→ birincil anahtar=NS,
seri hale getirmek=YANLIŞ, ayrıntılı_adı='İD')) ('stil',
modeller.CharField(maks_uzunluk=10),
seçimler=[('Şeker', 'Şeker'), ('gözleme',
↪
→ 'Gözleme')]),
('kepçe', modeller.OneToOneField(boş=NS,
↪
→ ile='kepçe.Kepçe'
on_delete=django.db.modeller.silme.SET_NULL,
↪
→ ) ),
],
),
# RunPython.noop ters geçişlere izin vermekten başka bir şey yapmaz
↪
→ ceryan etmek
göçler.RunPython(add_cones, geçişler.RunPython.hayır)
]
göç veriyor.
a Dağıtımdan önce, geçişleri geri alıp alamayacağınızı kontrol edin! her zaman sahip olamayız
mükemmel gidiş-dönüşler, ancak daha önceki bir duruma geri dönememek, hata izlemeyi ve bazen
a Bir projede milyonlarca satır içeren tablolar varsa verilere karşı kapsamlı testler yapın
bir üretim sunucusunda bir geçiş çalıştırmadan önce hazırlama sunucularında bu boyuttan.
Gerçek veriler üzerindeki geçişler, tahmin edilenden çok, çok, çok daha fazla zaman alabilir.
a MySQL kullanıyorsanız:
a Herhangi bir şema değişikliğinden önce kesinlikle olumlu bir şekilde veritabanını yedeklemelisiniz.
MySQL, şema değişiklikleri etrafında işlem desteğinden yoksundur, bu nedenle geri alma
imkansızdır.
a Dikkatli olunmazsa, yoğun olarak doldurulmuş tablolardaki şema değişiklikleri uzun zaman alabilir.
Şekil 6.1: Kış için güneye göç eden koniler. Django'nun yerleşik geçiş sistemi, South
adlı harici bir proje olarak başladı.
VCS'ye geçiş kodunun dahil edilmesi mutlak bir zorunluluktur. Sürüm kontrolüne geçiş
kodunun dahil edilmemesi, VCS'deki ayar dosyalarının dahil edilmemesine benzer:
Geliştirme yapabilirsiniz, ancak makineleri değiştirirseniz veya projeye başka birini
getirirseniz, her şey bozulur.
Erken optimizasyon yapmadan performans için nasıl tasarım yaparsınız? Burada bazı stratejileri
keşfedelim.
a en.wikipedia.org/wiki/Database_normalization en.wikibooks.org/wiki/
a Relational_Database_Design/Normalization
Django modellerinizi tasarlarken, her zaman normalleştirilmiş olarak başlayın. Hiçbir modelin başka bir
modelde depolanmış verileri içermediğinden emin olmak için zaman ayırın.
Bu aşamada ilişki alanlarını özgürce kullanın. Erken denormalize etmeyin. Verilerinizin şekli
hakkında iyi bir fikir sahibi olmak istiyorsunuz.
Çoğu zaman, önbelleğe almayı doğru yerlerde ayarlamak, modellerinizi denormalize etme zahmetinden
kurtarabilir. Önbelleğe almayı çok daha ayrıntılı olarak şurada ele alacağız:Bölüm 26: Darboğazları Bulma ve
Özellikle veri normalleştirme kavramlarına yeni başlayanlar için zamanından önce denormalize
etmek cazip gelebilir. yapma! Denormalizasyon, bir projede sorunlara neden olan şey için her
derde deva gibi görünebilir. Ancak, projenize karmaşıklık ekleme riskini taşıyan ve veri kaybetme
riskini önemli ölçüde artıran zor bir süreçtir.
Bir proje, aşağıda açıklanan tekniklerin sınırlarına ulaştığında Bölüm 26: Darboğazları
Bulma ve Azaltma ele alabilir, o zaman veritabanı denormalizasyonunun kavramları ve
kalıpları üzerine araştırma başlamalıdır.
Bu seçeneklerin ne zaman kullanılacağını bilmek, geliştiriciler için yaygın bir kafa karışıklığı kaynağıdır.
masa koyduk Tablo 6.2: Alana Göre Boş ve Boş Ne Zaman Kullanılır birlikte bu model alan argümanlarının
Bu alan, ham ikili verilerin veya bayt. Sahada filtreler, hariç tutmalar veya diğer SQL eylemleri
gerçekleştiremiyoruz, ancak bunun için kullanım durumları var. Örneğin, şunları saklayabiliriz:
Olasılıklar sonsuzdur, ancak ikili verilerin büyük parçalar halinde gelebileceğini ve veritabanlarını
yavaşlatabileceğini unutmayın. Bu meydana gelir ve bir darboğaz haline gelirse, çözüm ikili
verileri bir dosyaya kaydetmek ve ona birDosya Alanı.
Dosyaları bir veritabanı alanında saklamak asla gerçekleşmemelidir. Bir soruna çözüm
olarak görülüyorsa, sertifikalı bir veritabanı uzmanı bulun ve ikinci bir görüş isteyin.
PostgreSQL uzmanı Frank Wiles'ı bir dosya deposu olarak bir veritabanı kullanmayla ilgili
sorunları özetlemek için:
a 'bir DB'ye okuma/yazma her zaman bir dosya sisteminden daha yavaştır'
Birisi bir veritabanından dosya sunmak için iyi bir kullanım örneği olduğunu düşündüğünde ve
aşağıdaki gibi bir başarıdan alıntı yaptığında npmjs.org (CouchDB'de saklanan dosyalar),
araştırmanızı yapmanın zamanı geldi. Gerçek şu kinpmjs.org, dosya deposu olarak veritabanı
sistemini yıllar önce daha geleneksel bir dosya sunma yöntemine taşıdı.
İçinde Genel Biz savunucu karşısında Genel ilişkiler ve kullanmak ile ilgili
Genel ilişkiler fikri, bir tabloyu diğerine kısıtlanmamış bir yabancı anahtar aracılığıyla bağlamamızdır (
GenelYabancıAnahtar). Bunu kullanmak, gerçekten yabancı anahtar kısıtlamaları kullanabilecek projeler
için temel olarak yabancı anahtar kısıtlamaları olmayan bir NoSQL veri deposu kullanmaya benzer. Bu,
aşağıdakilere neden olur:
Bu kısıtlama eksikliğinin iyi tarafı, genel ilişkilerin, yaratmış olabileceğimiz çok sayıda model türüyle
etkileşime girmesi gereken şeyler için uygulamalar oluşturmayı kolaylaştırmasıdır. Özellikle favoriler,
derecelendirmeler, oylama, mesajlar ve etiketleme uygulamaları gibi şeyler. Gerçekten de, bu şekilde
oluşturulmuş bir dizi mevcut uygulama var. Bunları kullanmakta tereddüt etsek de, iyi olanların tek bir
göreve (örneğin etiketleme) odaklanması bizi teselli ediyor.
# siparişler/modeller.py
itibaren django.db içe aktarmak modeller
sınıf DondurmaSiparişi(modeller.modeli):
LEZZET_ÇİKOLATA = 'ç'
FLAVOR_VANILLA = 'vn'
LEZZET_ÇİLEK = 'NS'
FLAVOR_CHUNKY_MUNKY = 'santimetre'
LEZZET_SEÇİMLERİ = (
(LOZ_ÇİKOLATA, 'Çikolata'), (FLAVOR_VANILLA,
'Vanilya'), (LEZİ_ÇİLEK, 'Çilek'),
(FLAVOR_CHUNKY_MUNKY, 'Tıknaz Mıknatıs')
seçimler=LEZZET_CHOICES
)
>>>
↪
→ DondurmaSiparişi.nesneler.filtre (tat=DondurmaSiparişi.LEZZET_ÇİKOLATA) [<dondurma
siparişi: 35>, <dondurma siparişi: 42>, <dondurma siparişi: 49>]
Bu, hem Python kodunda hem de şablonlarda çalışır ve özniteliğe, sınıftan veya
örneklenmiş model nesnesinden erişilebilir.
Nate Cox, seçimler için Django'nun numaralandırma türlerinin kullanılmasını önerir. 3.0 sürümünden itibaren
sınıf DondurmaSiparişi(modeller.modeli):
sınıf tatlar(modeller.MetinSeçenekleri):
ÇİKOLATA = 'ç', 'Çikolata'VANİLYA = 'vn', 'Vanilya'
ÇİLEK = 'NS', 'Çilek'CHUNKY_MUNKY =
'santimetre', 'Tıknaz Mıknatıs'
seçimler=tatlar.seçimler
)
>>>
↪
→ DondurmaSiparişi.nesneler.filtre (tat=DondurmaSiparişi.tatlar.ÇİKOLATA) [<dondurma
siparişi: 35>, <dondurma siparişi: 42>, <dondurma siparişi: 49>]
Önceki yönteme göre numaralandırma türlerini kullanmanın birkaç dezavantajı vardır. özellikle:
gerekecek.
a Bunun dışında başka türler istiyorsak cadde ve int, bunları kendimiz tanımlamalıyız.
Seçim alanları için numaralandırma türleri, hoş bir API sağlar. Bunları kullanmak için mükemmel bir
yaklaşım bulduk, yukarıda listelenen dezavantajlarla karşılaşana kadar onlara bağlı kalmak. Daha
sonra eski tuple tabanlı yönteme geçiyoruz.
a Django'nun diğer _-önekli bileşenlerinden farklı olarak _meta aynı kullanımdan kaldırmayı takip eder
Bunun nedeni, Django 1.8'den önceki modelin _meta API, bildirimde bulunmaksızın değiştirilebilir
herhangi bir API'de normal olduğu gibi gayri resmiydi ve kasıtlı olarak belgelenmedi. _'nin asıl amacı
meta Django'nun kendi kullanımı için modeller hakkında fazladan bilgi depolamasıydı. Ancak, o kadar
a Bir model için belirli bir alanın sınıfını (veya miras zincirini veya diğer bilgileri) alın
türetilmiştir).
a Bu bilgiyi nasıl edindiğinizin gelecekteki Django sürümlerinde sabit kaldığından emin olun.
iyonlar.
a Görselleştirme veya analiz kitaplıkları yazma, ör. yalnızca alanlarla ilgili bilgileri analiz etme
"foo" ile başlayın.
sınıf YayınlananYönetici(modeller.Yönetici):
sınıf Lezzetİnceleme(modeller.modeli):
gözden geçirmek = modeller.CharField(maks_uzunluk=255)=
pub_date modeller.TarihSaatAlan()
Şimdi, önce tüm dondurma aroması incelemelerinin bir sayısını ve ardından sadece yayınlananların bir
sayısını görüntülemek istiyorsak, aşağıdakileri yapabiliriz:
Kolay değil mi? Yine de ikinci bir model yöneticisi ekleseniz daha mantıklı olmaz mıydı? Bu
şekilde şöyle bir şeye sahip olabilirsiniz:
Yüzeyde, varsayılan model yöneticisini değiştirmek akıllıca bir şey gibi görünüyor. Ne yazık ki,
gerçek proje geliştirme konusundaki deneyimlerimiz bu yöntemi kullanırken bizi çok dikkatli
yapıyor. Niye ya?
Her zaman ayarla nesneler = modeller.Yönetici() yeni bir ada sahip herhangi bir özel
model yöneticisinin üstünde. Bu kural çiğnenebilir olsa da, çoğu proje için
önermediğimiz gelişmiş bir tekniktir.
Ek okuma: docs.djangoproject.com/en/3.2/topics/db/managers/
ve ayrıca elektronik tabloları kabul eden bir içe aktarma aracından çağrılır.
a İnceleme.product_average İnceleneni döndüren bir inceleme örneği özelliği
ürünün ortalama puanı. Okuyucunun sayfadan ayrılmadan genel görüş hakkında bir fikir edinebilmesi
Bu listeden de anlaşılacağı gibi, şişman modeller, bir projede kodun yeniden kullanımını
iyileştirmenin harika bir yoludur. Aslında, mantığı görünümlerden ve şablonlardan modellere
taşıma pratiği, projeler, çerçeveler ve diller arasında yıllardır büyüyor. Bu iyi bir şey, değil mi?
Şart değil.
Tüm mantığı modellere yerleştirmekle ilgili sorun, modellerin kod boyutunda patlamasına ve ' olarak
adlandırılan hale gelmesine neden olabilmesidir.tanrı nesnesi'. Bu anti-kalıp, şu model sınıflarıyla sonuçlanır:
Mantığı modellerden ve faydalı fonksiyonlara taşıyarak daha izole hale gelir. Bu izolasyon,
mantık için testler yazmayı kolaylaştırır. Dezavantajı, işlevlerin durumsuz olmasıdır, bu
nedenle tüm argümanların iletilmesi gerekir.
Bize göre, bu tekniklerin hiçbiri tek başına mükemmel değildir. Ancak her ikisi de akıllıca
kullanıldığında projelerin parlamasını sağlayabilir. Her ikisinin de ne zaman kullanılacağını anlamak
statik bir bilim değil, gelişen bir süreçtir. Bu tür bir evrim yanıltıcıdır ve bizim önerimizi yağ
modellerinin bileşenleri için testler yaptırmamıza neden olur.
6.8 Ek Kaynaklar
İşte bu bölümde örneklediklerimizi temel alan birkaç makale:
a- Andrew Brooks'un Django'nun ORM'sine yaptığı derin dalış herkes için okumaya değer
model tasarımının performansıyla ilgilenirler. Spellbookpress.com/
kitaplar/tapınak-django-veritabanı-performans/
6.9 Özet
Modeller çoğu Django projesinin temelidir, bu yüzden onları dikkatlice tasarlamak için
zaman ayırın.
Model mirasını kullanmaya karar verirseniz, somut modeller yerine soyut temel sınıflardan miras alın.
Kendinizi örtük, gereksiz birleştirmelerle uğraşmanın karmaşasından kurtaracaksınız.
Son olarak, şişman modeller, modellerde mantığı kapsüllemenin bir yoludur, ancak hepsi çok kolay bir şekilde tanrı nesnelerine
dönüşebilir.
Bir sonraki bölümümüz, sorgular ve veritabanı katmanı hakkında konuşmaya başlayacağımız yerdir.
Yazdığımız sorguların çoğu basittir. Django'nunNesne-İlişkisel Model veya ORM harika bir
üretkenlik kısayolu sağlar: yalnızca yaygın kullanım durumları için uygun SQL sorguları
oluşturmakla kalmaz, aynı zamanda doğrulama ve güvenlikle birlikte gelen model erişimi/
güncelleme işlevselliği sağlar. Farklı veritabanı motorlarıyla çalışan önemsiz bir şekilde kod
yazmamızı sağlar. ORM'lerin bu özelliği, Django üçüncü taraf paket ekosisteminin çoğuna güç
sağlar. ORM ile sorgunuzu kolayca yazabiliyorsanız, bundan yararlanın!
Django ORM, herhangi bir ORM gibi, farklı türlerdeki verileri desteklenen veritabanlarında oldukça
tutarlı bir şekilde kullanabileceğimiz nesnelere dönüştürür. Ardından, bu nesnelerle etkileşim için bir
dizi yöntem sağlar. Çoğunlukla, Django yapmak için tasarlandığı şeyde oldukça iyi bir iş çıkarıyor.
Ancak, tuhaflıkları vardır ve bu tuhaflıkları anlamak, Django'nun nasıl kullanılacağını öğrenmenin bir
parçasıdır. Bazılarının üzerinden geçelim, olur mu?
a Yardımcı işlevlerde, formlarda, model yöntemlerinde veya herhangi bir şeyde kullanmayın.
Yıllar önce, Daniel adında belirli bir Python kodlayıcısı ve yazarı ilk Django
projesini dağıtıyordu. O kadar büyülenmişti ki Django'nunget_object_or_404()
her yerde, görünümlerde, modellerde, formlarda, her yerde kullandığı işlevi.
Geliştirmede bu harika çalıştı ve testleri geçti. Ne yazık ki, bu kısıtlamasız kullanım,
yönetici personel tarafından belirli kayıtlar silindiğinde tüm sitenin bozulması anlamına
geliyordu.
Ancak, diğer birçok durumda bir try-except bloğu kullanmanız gerekir. Bazı ipuçları:
Nesne Yok Yok herhangi bir model nesnesine uygulanabilir, oysa Bulunmuyor belirli bir
model içindir.
tanım list_flavor_line_item(sku):
denemek:
tanım list_flavor_line_item(sku):
denemek:
# Bunu yapma!
itibaren django.db.modelleri içe aktarmak Q
tanım eğlence_fonksiyonu(isim=Hiçbiri):
↪
→ # Çok fazla sorgu zinciri, kodun ekrandan veya sayfadan çıkmasına neden olur. İyi değil.
dönüş
↪
→ Promo.objects.active().filter(Q(name__startswith=name)|Q(description__icontains
Bu hoş değil, değil mi? Yine de gelişmiş Django ORM araçlarını eklersek, o zaman tatsızdan
sriracha bazlı bir dondurma kadar korkunç hale gelir. Bu tatsızlığı azaltmak için, ORM
kodumuzu temiz tutmak için Django sorgularının tembel değerlendirme özelliğini
kullanabiliriz.
Tembel değerlendirme ile, Django ORM'nin verilere gerçekten ihtiyaç duyulana kadar SQL çağrıları
yapmadığını kastediyoruz. ORM metodlarını ve fonksiyonlarını istediğimiz kadar zincirleyebiliriz,
ve biz sonuç arasında dolaşmaya çalışana kadar Django veritabanına dokunmaz. Birçok
yöntemi ve gelişmiş veritabanı özelliklerini tek bir satırda zincirlemek zorunda kalmak
yerine, bunları gerektiği kadar satıra bölebiliriz. Bu, okunabilirliği artırır, bu da bakım
kolaylığını artırır, bu da dondurma alma süresini artırır.
Buradan kodu alıyoruz kötü örnek 7.3 ve daha okunaklı bir koda bölün:
# Bunu yap!
itibaren django.db.modelleri içe aktarmak Q
tanım eğlence_fonksiyonu(isim=Hiçbiri):
Düzeltilmiş kodda da görüldüğü gibi, sonucun ne olacağını daha kolay söyleyebiliriz. Daha
da iyisi, sorgu ifadesini bölerek belirli kod satırları hakkında yorum yapabiliriz.
Bu teknik, Pandalar ve JavaScript topluluklarından ödünç alınmıştır. Tembel değerlendirme kullanmak yerine
# Bunu yap!
itibaren django.db.modelleri içe aktarmak Q
tanım eğlence_fonksiyonu(isim=Hiçbiri):
qs = (promosyon
. nesneler
. aktif()
. filtre(
Q(name__startwith=isim) |
Q(açıklama__icontains=isim)
)
. hariç tut(durum='erimiş')
. seçici_ilgili('tatlar')
)
dönüş qs
Bu yaklaşımın dezavantajı, hata ayıklamanın, bir sorgu yazmanın tembel değerlendirme yöntemini kullanmak kadar
kolay olmamasıdır. Biz sadece bir tane yapıştıramayızPDB veya IPDB bu şekilde tanımlanmış bir sorgunun ortasında
çağrı yapın.
tanım eğlence_fonksiyonu(isim=Hiçbiri):
. nesneler
. aktif()
# . filtre(
# S(isim__startswith=isim) |
# S(açıklama__icontains=ad)
#)
# . hariç tut(durum='erimiş')
# . select_ Related('tatlar')
)
kesme noktası()
dönüş qs
verileri Python'dan (veya Ruby, JavaScript, Go, Java ve diğerleri) daha hızlı yönetir ve dönüştürür.
Verileri Python ile yönetmek yerine, kaldırmayı yapmak için her zaman Django'nun gelişmiş sorgulama araçlarını
kullanmaya çalışıyoruz. Bunu yaparken yalnızca artırılmış performanstan faydalanmakla kalmıyoruz, aynı zamanda
oluşturduğumuz Python tabanlı geçici çözümlerden daha kanıtlanmış (Django ve çoğu veri tabanı sürekli test ediliyor)
İlk olarak, sorgu ifadeleri olmadan tehlikeli de olsa bunun nasıl yapılabileceği:
# Bunu yapma!
itibaren modeller.müşteriler içe aktarmak Müşteri
müşteriler = []
için Customer.objects.iterator() içindeki müşteri:
Eğer client.scoops_ordered > customer.store_visits:
müşteriler.append(müşteri)
a Veritabanındaki tüm Müşteri kayıtlarını tek tek dolaşmak için Python'u kullanır.
Bu yavaş ve bellek tüketiyor.
a Herhangi bir kullanım hacmi altında, yarış koşulları yaratacaktır. Bu, biz olduğumuzda ortaya çıkar
müşteriler verilerle etkileşime girerken komut dosyasını çalıştırmak. Bu basit 'OKU' örneğinde
muhtemelen bir sorun olmasa da, gerçek dünya kodunda bunu bir 'GÜNCELLEME' ile
birleştirmek veri kaybına neden olabilir.
Neyse ki, sorgu ifadeleri aracılığıyla Django, bunu daha verimli ve yarış koşulundan bağımsız hale
getirmenin bir yolunu sunar:
müşteriler =
↪
→ Müşteri.nesneler.filtre(scoops_ordered__gt=F('mağaza_ziyaretleri'))
Bunun yaptığı, karşılaştırmayı gerçekleştirmek için veritabanının kendisini kullanmaktır. Kaputun altında,
a docs.djangoproject.com/en/3.2/ref/models/expressions/
Referans:
a docs.djangoproject.com/en/3.2/ref/models/database-functions/
Peki ne zaman ham SQL yazmalısınız? Sorgunuzu ham SQL olarak ifade etmek Python kodunuzu
veya ORM tarafından oluşturulan SQL'i büyük ölçüde basitleştirecekse, devam edin ve yapın.
Örneğin, her biri büyük bir veri kümesi üzerinde çalışan bir dizi QuerySet işlemini
zincirliyorsanız, onu ham SQL olarak yazmanın daha verimli bir yolu olabilir.
a İndekslemenin sonuçlarda bir iyileşme sağlayıp sağlamadığını belirlemek için testler yapabiliriz.
Bir proje hayata geçtiğinde, Bölüm 26: Darboğazları Bulma ve Azaltma, indeks analizi hakkında
bilgi sahibidir.
a docs.djangoproject.com/en/3.2/ref/models/indexes/
a docs.djangoproject.com/en/3.2/ref/models/options/
# dizin
7.7 İşlemler
ORM'nin varsayılan davranışı, çağrıldığında her sorguyu otomatik olarak yerine getirmektir. Veri
değişikliği durumunda, bu, her seferinde bir .oluşturmak() veya .Güncelleme() çağrıldığında, SQL
veritabanındaki verileri hemen değiştirir. Bunun avantajı, yeni başlayan geliştiricilerin ORM'yi
anlamasını kolaylaştırmasıdır. Dezavantajı, bir görünüm (veya başka bir işlem) iki veya daha fazla
veritabanı değişikliğinin gerçekleşmesini gerektiriyorsa, bir değişiklik başarılı ve diğeri başarısız
olursa, veritabanı bozulma riski altındadır.
Django, güçlü ve nispeten kullanımı kolay bir işlem mekanizmasına sahiptir. Bu, dekoratörleri ve
bağlam yöneticilerini oldukça sezgisel bir modelde kullanarak bir projedeki veritabanı bütünlüğünü
kilitlemeyi çok daha kolaylaştırır.
# settings/base.py
VERİTABANLARI = {
'varsayılan': {
#...
'ATOMİK_İSTEKLER': NS,
},
}
ATOMIC_REQUESTS ayar. olarak ayarlayarakNS yukarıda gösterildiği gibi, yalnızca veri okuyanlar da dahil
olmak üzere tüm istekler işlemlere sarılır. Bu yaklaşımın avantajı güvenliktir: görünümlerdeki tüm
veritabanı sorguları korunur, dezavantajı performansın düşebilmesidir. Bireysel veritabanı tasarımına
ve çeşitli veritabanı motorlarının kilitlemeyi ne kadar iyi idare ettiğine bağlı olduğundan, bunun
performansı ne kadar etkileyeceğini size söyleyemeyiz.
Bunun, yazma ağırlıklı bir projenin veritabanının bütünlüğünü korumasını başlangıçta sağlamak için harika bir
yol olduğunu bulduk. Ancak çok fazla trafik olduğu için geri dönüp işleri daha odaklı bir yaklaşımla değiştirmek
zorunda kaldık. Büyüklüğüne bağlı olarak bu, küçük veya anıtsal bir görev olabilir.
Core Django geliştiricisi ve yeni işlem sisteminin ana uygulayıcısı Aymeric Augustin,
“Bu dekoratör, görünümler ve modeller arasında sıkı bir bağlantı gerektiriyor ve bu
da bir kod tabanının bakımını zorlaştıracak. Geriye dönük uyumluluk sağlamak
zorunda kalmasaydık daha iyi bir tasarım bulabilirdik.”
Ardından, bu süper basit API stili işlev tabanlı görünümde aşağıda açıklandığı gibi daha açık
bildirimi kullanabilirsiniz:
# tatlar/views.py
@işlem.non_atomic_requests
tanım posting_flavor_status(istek, pk, durum):
Bu tür projeler için, sistemleri işlemsel bütünlük yerine nihai tutarlılık için
tasarlayın. Başka bir deyişle, işlemlerin başarısız olmasına ve geri dönüşlerin
gerçekleşmesine hazır olun. Neyse ki, işlemler nedeniyle, geri alma ile bile
veriler doğru ve temiz kalacaktır.
İşlemler söz konusu olduğunda, yaşamanız gereken bazı iyi yönergeler şunlardır:
Bu yeterince açık değilse, farklı Django ORM çağrılarının işlemlere ne zaman sarılması
gerektiğini açıklayan bir tablo burada.
Şekil 7.2: Çünkü kimse dondurmayı bir veri tabanı gibi sevmez.
Bunu da kapsıyoruz Bölüm 26: Darboğazları Bulma ve Azaltma, özellikle alt bölümBölüm
26.2.4: ATOMIC_REQUESTS'i False olarak değiştirin.
Bu nedenle, tek bir ORM yöntemini sarmak hiçbir zaman yararlı değildir [.oluşturmak(), .
güncelleme(), .delete()]bir işlemde arayın. Bunun yerine, bir görünümde, işlevde veya
yöntemde birkaç ORM yöntemini çağırırken açık işlemleri kullanın.
kullanabileceğinizi unutmayınız. ATOMIC_REQUESTS bir akış yanıtı ile, ancak işlem yalnızca
görünümün kendisine uygulanacaktır. Yanıt akışının oluşturulması ek SQL sorgularını
tetiklerse, bunlar otomatik taahhüt modunda yapılacaktır. Umarım bir yanıt oluşturmak,
veritabanı yazma işlemlerini tetiklemez ...
a docs.djangoproject.com/en/3.2/topics/db/transactions/
# işlemler-in-mysql dev.mysql.com/doc/refman/8.0/en/sql-transactional-ifadeleri.
a html
7.8 Özet
Bu bölümde, bir projenin kalıcı verilerini sorgulamanın farklı yollarını inceledik.
Verilerin proje boyunca gerçekte nasıl çalıştığına dair daha iyi bir fikir edindikten sonra dizinleri
kullanmanızı öneririz.
Artık verilerin nasıl saklanacağını ve indeksleneceğini bildiğimize göre, şimdi onu göstermeye başlayalım. Bir sonraki
Hem işlev tabanlı görünümler (FBV'ler) hem de sınıf tabanlı görünümler (CBV'ler), Django'nun temel bir
Hangi yöntemi seçeceğinizden emin değilseniz, bir sonraki sayfada size yardımcı olabilecek bir
akış şeması ekledik.
Bu akış şeması, FBV'ler yerine CBV'leri kullanma tercihimizi takip eder. Çoğu görünüm için CBV'leri kullanmayı,
yalnızca özel hata görünümlerini veya CBV'lerle uygulanması zahmetli olacak karmaşık olanları uygulamak için
Bazı geliştiriciler, çoğu görünüm için FBV'leri ve yalnızca alt sınıflanması gereken görünümler için
Yine de, Daniel'in ne zaman karmaşık görse bağırmak gibi hissettiği şey bu. urls.py Dosyalar:
“J2EE XML ve Zope ZCML konfigürasyon dosyalarını o gün yazmadım ki siz çocuklar
Django url modüllerine mantık sokabilesiniz diye!”
Django'nun URL rotalarını tanımlamanın harika ve basit bir yolu olduğunu unutmayın. Bu kitapta
bahsettiğimiz diğer her şey gibi, bu basitliğe de saygı duyulmalı ve saygı duyulmalıdır. Temel kurallar
şu şekildedir:
Hiç böyle kod gördünüz mü? Belki de Sınıf Tabanlı Görünümler için resmi belgelerde?
# Bunu yapma!
itibaren django.urls içe aktarmak yol
itibaren django.views.jenerik içe aktarmak Detay Görünümü
url kalıpları = [
yol('<int:pk>',
DetailView.as_view(
model=Tadım,
şablon_adı='tadımlar/detay.html'), isim='detay'),
yol('<int:pk>/sonuçlar/',
DetailView.as_view(
model=Tadım,
şablon_adı='tadımlar/sonuçlar.html'), isim='Sonuçlar'),
Bir bakışta bu kod uygun görünebilir, ancak Django tasarım felsefelerini ihlal ettiğini iddia
ediyoruz:
Önceki sayfada bahsettiğimiz sorunlardan kaçınan URLConf'leri nasıl oluşturacağınız aşağıda açıklanmıştır. İlk
model = Tatma
model = Tatma
tanım get_success_url(öz):
dönüş ters('tatma:detay',
kwarglar={'pk': öz.nesne.pk})
url kalıpları = [
yol(
güzergah='',
görüş=Görüntüleme.Tat Listesi Görünümü.
as_view(), isim='liste'
),
yol(
güzergah='<int:pk>/',
görüş=Görüntüleme.TatAyrıntılı Görünüm.
as_view(), isim='detay'
),
yol(
güzergah='<int:pk>/sonuçlar/',
görüş=Görüntüleme.TatSonuçlarGörünüm.as_view(),
isim='Sonuçlar'
),
yol(
güzergah='<int:pk>/güncelleme/',
görüş=Görüntüleme.Tat Güncelleme Görünümü.as_view(),
isim='Güncelleme'
)
]
Bu versiyonumuza ilk cevabınız şöyle olmalı, “Bunun iyi bir fikir olduğundan emin misin? İki dosya VE
daha fazla kod satırı kullanmak için bazı şeyleri değiştirdiniz! Bu nasıl daha iyi?”
a Kendinizi Tekrar Etmeyin : Görünümler arasında hiçbir argüman veya nitelik tekrarlanmaz.
a URLConfs bir şey yapmalı ve onu iyi yapmalıdır: Bir önceki maddemiz ile ilgili olarak,
URLConf artık yalnızca tek bir şeye odaklanıyor: URL yönlendirme. Hem görünümler hem de
URLConf'ler arasında görünüm mantığını izlemiyoruz, sadece görüşlerimize bakıyoruz.
a Görüşlerimiz sınıf temelli olmaktan yararlanır: Resmi bir tanım yaparak görüşlerimiz
görünümler modülünde diğer sınıflardan miras alabilir. Bu, kimlik doğrulama, yetkilendirme,
yeni içerik biçimleri veya önümüze atılan diğer iş gereksinimlerinin eklenmesinin çok daha kolay
olduğu anlamına gelir.
a sonsuz esneklik: Görüşlerimiz, görünümler modülünde resmi bir tanım yaparak,
kendi özel mantığını uygular.
Kapsamlı URLConf korsanlığı ile FBV'leri kullanan projelerin hata ayıklama kabuslarıyla
karşılaştık, örneğin, Python modüllerinin __file__ özniteliği ile birleştirilmiş dizin yürüyüşü ve
URLConf'leri otomatik olarak oluşturmak için düzenli ifadeler gibi ayrıntılı hileler gibi. Kulağa acı
verici geliyorsa, öyleydi.
Bunun neden bu kadar yararlı olduğunu açıklamadan önce, örnek 8.2'deki uygulama düzeyinde
URLConf kodunu temel alan bir kullanım örneği sunacağız. URLConf kök dizinine şunları ekleriz:
url kalıpları += [
yol('tadım/', Dahil etmek('tadım.url',
↪
→ ad alanı='tadım')),
]
Bunu bir görünümde çalışırken görmek için, örnek 8.1'den bir kod parçacığına bakalım:
tanım get_success_url(öz):
dönüş ters('tatma:detay',
kwarglar={'pk': öz.nesne.pk})
{% uzanır 'temel.html' %}
{% engellemek içerik %}
<ul>
{% için damak zevki içinde tadımlar %}
<li>
<a href="{% url 'tadımlar:detay' tat.pk %}">{{ tat.başlık
↪
→ }}</a>
<küçük>
(<a href="{% url 'tadımlar:güncelleme' tat.pk %}">güncelleme</a>) </small>
</li>
{% son %}
</ul>
{% uç blok içerik %}
Artık URL ad alanlarının nasıl uygulanacağını anladığımıza göre, neden yararlı olduklarını ele
alalım.
Ayrıca, kim "tadım" veya bir uygulamaya ne denirse yazmak ister ki bu kadar çok kez?
< gibi URL adları yazmanın sorunlarından biriuygulamam>_detay uygulama adlarının çakıştığı
zamandır. Bu bizim gibi şeyler için bir sorun olmasa datadımlar app, blog ve iletişim
uygulamaları ile kesinlikle yazarların başına geldi. Neyse ki, URL ad alanları bunu çözmeyi
kolaylaştırır. Mevcut bir kişi uygulamamız olduğunu, ancak ikinci bir tane eklememiz gerektiğini
varsayarsak, URL ad alanlarını kullanarak bunları şu şekilde kök URLConf'umuza entegre
edebiliriz:
↪
→ ad alanı='temas tüccarı')),
yol('rapor sorunu/', Dahil etmek('contactapp.urls',
↪
→ ad alanı='contactapp')),
]
{% uzanır "temel.html" %}
{% engellemek Başlık %}Temas{% uç blok Başlık %} {%
engellemek içerik %}
<p>
<a href="{% url 'iletişim kuryesi:oluştur' %}">Bize Ulaşın</a> </p>
<p>
<a href="{% url 'iletişim uygulaması:rapor' %}">Sorun Bildir</a> </p>
{% uç blok içerik %}
Django gibi PEP 8 dostu çerçeveler için adlarda alt çizgilerin yaygınlığı göz önüne
alındığında, arama kodu veya “ gibi adlartadımlar_detay” zorlayıcı olabilir. Bir sonuç
geldiğinde, bu bir görünüm adı, bir URL adı veya başka bir şey için mi?
Öte yandan, "tadımlar:detay” sezgisel arama sonucu yanıtları sağlar. Bu, yeni üçüncü taraf
kitaplıklarıyla etkileşim kurarken de dahil olmak üzere uygulamaların ve projelerin
yükseltilmesini ve yeniden düzenlenmesini kolaylaştırabilir ve yaptı.
Burada hiçbir numarayı ele almayacağız çünkü bu tür şeylerin neredeyse hiçbir zaman haklı olmadığını
düşünüyoruz. Aslında, genellikle herhangi bir somut fayda sağlamadan bir projenin karmaşıklığına katkıda
hesap.
Geliştiriciler, her zaman olduğu gibi, yaratıcı URL ad alanları hilelerinin kullanımını doğrulamak için bunlardan herhangi
Burada tercih ettiğimiz model yöntemleri, yönetici yöntemleri veya genel yardımcı işlevler yaklaşımımız
devreye girer. İş mantığı, kolayca yeniden kullanılabilir bileşenlere yerleştirildiğinde ve görünümlerin
içinden çağrıldığında, daha fazla şeyi yapmak için projenin bileşenlerini genişletmeyi çok daha kolay
hale getirir.
Bunu bir projenin başında yapmak her zaman mümkün olmadığı için, görüşler
arasında Django ortak plakası yerine iş mantığını kopyaladığımızda temel kuralımız,
kodu görünümden çıkarmanın zamanı geldi.
Bu değişim kavramı, Django görünümleriyle, işlev veya sınıf tabanlı olsun, yapabileceğiniz her
türlü şey için bir temel görevi görür.
Bunu akılda tutarak, Django ile oluşturulabilecek olası en basit görünümleri hatırlamakta
fayda var:
# En basit FBV
tanım en basit görünüm(rica etmek):
# İş mantığı buraya giderdönüş
HttpResponse('FBV')
a En basit Django görünümlerini anlamak, onların ne olduklarını daha iyi anlamamız anlamına gelir.
gerçekten yapıyor.
a Django FBV'lerin HTTP yönteminin nasıl tarafsız olduğunu, ancak Django CBV'lerin nasıl gerekli olduğunu gösterir
# Bunu yapma!
tanım ice_cream_store_display(istek, mağaza_kimliği):
mağaza = get_object_or_404(Mağaza, id=store_id) tarih =
saat dilimi.now()
dönüş render (istek, 'melted_ice_cream_report.html',
↪
→ yerliler())
Ancak, açık bir tasarımdan örtülü anti-kalıba geçtik ve bu basit görünümün sürdürülmesi can
sıkıcı hale getirdik. Özellikle, görünümün ne döndürmesi gerektiğini bilmediğimizi. Görünüm
tarafından döndürülen değişkenlerden herhangi birinin değiştirilmesi hemen belli olmadığı için
bu bir sorun haline gelir:
# Bunu yapma!
tanım ice_cream_store_display(istek, mağaza_kimliği):
store = get_object_or_404(Mağaza, id=store_id) şimdi =
saat dilimi.now()
dönüş render (istek, 'melted_ice_cream_report.html',
↪
→ yerliler())
Kötü Örnek 8.11 ile Kötü Örnek 8.12 arasındaki farkı anlamanız ne kadar sürdü? Bu basit
bir örnekti, büyük bir şablonla daha karmaşık bir örnek hayal edin. Bu nedenle, görüşlerde
açık bağlamın kullanılmasını şiddetle savunuyoruz:
8.8 Özet
Bu bölüm, FBV'lerin veya CBV'lerin ne zaman kullanılacağını tartışarak başladı ve ikincisi için
kendi tercihimize uydu. Aslında, bir sonraki bölümde, FBV'ler kullanılırken yararlanılabilecek
işlevselliklerin derinliklerine inmeye başlayacağız ve bunu CBV'ler üzerine bir bölüm izleyecektir.
Ayrıca görünüm mantığını URLConf'lerin dışında tutmayı da tartıştık. Görünüm kodunun uygulamalara ait
uygulamaya bağlı kalmak, sınıf tabanlı görünümler, daha kolay kod yeniden kullanımı ve daha fazla tasarım