Django'nun Öne Çıkanları: Statik Varlıkları ve Medya Dosyalarını Uğraşmak (4. Kısım)
Yayınlanan: 2022-03-10Django web siteleri çok sayıda dosya içerir. Yalnızca yapılandırma, modeller, görünümler ve şablonlar için kaynak kod değil, aynı zamanda statik varlıklar: CSS ve JavaScript, resimler, simgeler. Bu da yetmezmiş gibi, bazen kullanıcılar gelir ve kendi dosyalarını web sitenize yüklemek isterler. Herhangi bir geliştiriciyi inanılmaz hale getirmek için yeterlidir. Her yerde dosyalar!
İşte burada (uyarılar olmadan) söyleyebilmeyi isterdim: “Merak etmeyin, Django arkanızda!” Ancak ne yazık ki, statik varlıklar ve medya dosyalarıyla uğraşırken, uğraşılması gereken birçok uyarı vardır.
Bugün, sıkıştırma, önbelleğe alma ve kullanılabilirlik gibi faktörleri göz önünde bulundurarak hem tek sunuculu hem de ölçeklenebilir dağıtımlar için dosyaların depolanmasını ve sunulmasını ele alacağız. Ayrıca CDN'lerin ve özel dosya depolama çözümlerinin maliyet ve faydalarını da tartışacağız.
Not : Bu, bir Django sitesinin belirli bir platforma nasıl dağıtılacağına ilişkin bir eğitim değildir. Bunun yerine, Django Öne Çıkanlar serisindeki diğer makaleler gibi (aşağıya bakın), ön uç geliştiricilerin ve tasarımcıların bir web uygulaması oluşturma sürecinin diğer kısımlarını anlamaları için bir kılavuz olarak tasarlanmıştır. Bugün, yeni bitirdiğiniz stil düzeltmesi veya güzel grafiğin ustalaşmaya itilmesinden sonra ne olduğuna odaklanıyoruz. Birlikte, bu dosyaları dünya çapındaki kullanıcılara güvenli, performanslı ve uygun maliyetli bir şekilde sunmak için Django geliştiricilerinin kullanabileceği stratejiler için bir sezgi geliştireceğiz.
Serideki Önceki Parçalar :
- Bölüm 1: Kullanıcı Modelleri ve Kimlik Doğrulama
- Bölüm 2: Şablonlama Satırları Kurtarır
- Bölüm 3: Modeller, Yönetici ve İlişkisel Veritabanından Yararlanma
Tanımlar
Bu terimlerin çoğu oldukça basittir, ancak bu tartışma için ortak bir kelime dağarcığı oluşturmak için biraz zaman ayırmaya değer.
Canlı bir Django uygulamasındaki üç dosya türü şunlardır:
- Kaynak kodu
Django çerçevesiyle oluşturulan Python ve HTML dosyaları. Bu dosyalar uygulamanın çekirdeğidir. Kaynak kod dosyaları genellikle oldukça küçüktür ve kilobayt cinsinden ölçülür. - Statik Dosyalar
"Statik varlıklar" olarak da adlandırılan bu dosyalar, hem uygulama geliştiricisi hem de üçüncü taraf kitaplıkları tarafından yazılan CSS ve JavaScript'in yanı sıra PDF'ler, yazılım yükleyicileri, resimler, müzik, videolar ve simgeler içerir. Bu dosyalar yalnızca istemci tarafında kullanılır. Statik dosyalar, birkaç kilobayt CSS'den gigabaytlarca videoya kadar değişir. - Medya dosyaları
Profil resimlerinden kişisel belgelere kadar bir kullanıcı tarafından yüklenen herhangi bir dosyaya medya dosyası denir. Bu dosyaların güvenli ve güvenilir bir şekilde saklanması ve kullanıcı için alınması gerekir. Medya dosyaları herhangi bir boyutta olabilir, kullanıcı birkaç gigabaytlık videoya birkaç kilobaytlık düz metin yükleyebilir. Bu ölçeğin ikinci ucundaysanız, muhtemelen bu makalenin vermeye hazır olduğundan daha fazla özel tavsiyeye ihtiyacınız var.
İki tür Django dağıtımı şunlardır:
- Tek Sunucu
Tek sunuculu bir Django dağıtımı kulağa tam olarak benziyor: her şey tek bir sunucuda yaşıyor. Bu strateji çok basittir ve geliştirme ortamına çok benzer, ancak büyük veya tutarsız miktarda trafiği etkin bir şekilde idare edemez. Tek sunucu yaklaşımı, güvenilir çalışma süresi gerektiren gerçek sözcük uygulamaları için değil, yalnızca öğrenme veya gösterim projeleri için geçerlidir. - ölçeklenebilir
Kullanıcı talebini karşılayacak şekilde ölçeklenmesine olanak tanıyan bir Django projesini dağıtmanın birçok farklı yolu vardır. Bu stratejiler genellikle çok sayıda sunucuyu yukarı ve aşağı döndürmeyi ve yük dengeleyiciler ve yönetilen veritabanları gibi araçları kullanmayı içerir. Neyse ki, bu makalenin amaçları doğrultusunda, tek sunuculu bir dağıtımdan daha karmaşık olan her şeyi bu kategoriye etkili bir şekilde yerleştirebiliriz.
Seçenek 1: Varsayılan Django
Küçük projeler basit mimariden yararlanır. Django'nun statik varlıkları ve medya dosyalarını varsayılan olarak işlemesi tam da budur: basit. Her biri için, dosyaları depolayan ve sunucudaki kaynak kodun hemen yanında yaşayan bir kök klasörünüz var. Basit. Bu kök klasörler çoğunlukla yourproject/settings.py yapılandırmanız aracılığıyla oluşturulur ve yönetilir.
Statik Varlıklar
Django'da statik dosyalarla çalışırken anlaşılması gereken en önemli şey python manage.py collectstatic
komutudur. Bu komut, Django projesindeki her uygulamanın statik klasöründen geçer ve tüm statik varlıkları kök klasöre kopyalar. Bu komutu çalıştırmak, bir Django projesini dağıtmanın önemli bir parçasıdır. Aşağıdaki dizin yapısını göz önünde bulundurun:
- project - project - settings.py - urls.py - ... - app1 - static/ - app1 - style.css - script.js - img.jpg - templates/ - views.py - ... - app2 - static/ - app2 - style.css - image.png - templates/ - views.py - ...
Ayrıca project/settings.py dosyasında aşağıdaki ayarları da kabul edin:
STATIC_URL = "/static/" STATIC_ROOT = "/path/on/server/to/djangoproject/static"
python manage.py collectstatic
komutunu çalıştırmak, sunucuda aşağıdaki klasörü oluşturacaktır:
- /path/on/server/to/djangoproject/static - app1 - style.css - script.js - img.jpg - app2 - style.css - image.png
Her statik klasörün içinde uygulamanın adına sahip başka bir klasör olduğuna dikkat edin. Bu, statik dosyalar toplandıktan sonra ad alanı çakışmalarını önlemek içindir; Yukarıdaki dosya yapısında görebileceğiniz gibi bu, app1/style.css ve app2/style.css'yi farklı tutar. Buradan uygulama, üretim sırasında STATIC_ROOT
bu yapıdaki statik dosyaları arayacaktır. Bu nedenle, app1/templates/ içindeki bir şablonda statik dosyalara aşağıdaki gibi başvurun:
{% load static %} <link rel="stylesheet" type="text/css" href="{% static "app1/style.css" %}">
Django, bu davranışı modellemek için geliştirme sırasında statik dosyanın nereden alınacağını otomatik olarak bulur, geliştirme sırasında collectstatic
çalıştırmanız gerekmez.
Daha fazla ayrıntı için Django belgelerine bakın.
Medya dosyaları
Bir kullanıcı veri tabanına sahip profesyonel bir ağ sitesi hayal edin. Bu kullanıcıların her birinin, diğer şeylerin yanı sıra bir avatar resmi ve bir özgeçmiş belgesi içerebilen ilişkili bir profili olacaktır. İşte bu bilgilerin kısa bir örnek modeli:
from django.db import models from django.contrib.auth.models import User def avatar_path(instance, filename): return "avatar_{}_{}".format(instance.user.id, filename) class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) resume = models.FileField(upload_to="path/string") avatar = models.ImageField(upload_to=avatar_path)
Bunun çalışması için, statik varlıklarda olduğu gibi project/settings.py dosyasında aşağıdaki seçeneklere ihtiyacınız vardır:
MEDIA_URL = "/media/" MEDIA_ROOT = "/path/on/server/to/media"
Bir ImageField
, FileField
öğesinden devralır, dolayısıyla aynı parametreleri ve yetenekleri paylaşır. Her iki alanın da isteğe bağlı bir upload_to
argümanı vardır; bu, bir yol olan bir dizeyi alır ve dosyayı depolamak için MEDIA_ROOT
ekler ve daha sonra MEDIA_URL
üstünde aynı yoldan erişilebilir. upload_to
argümanı, avatar_path
işleviyle gösterildiği gibi, bir dize döndüren bir işlev de alabilir.
Medya dosyaları dizinini ve içeriğini sürüm kontrolünden çıkardığınızdan emin olun. İki geliştirici aynı uygulamayı farklı makinelerde test ettiğinde içeriği çakışabilir ve statik varlıkların aksine konuşlandırılabilir Django uygulamasının bir parçası değildir.
Seçenek 2: Hizmetlerle Django
Yol gösterici felsefem, araçları en iyi oldukları alanlarda kullanmaktır. Django harika bir çerçevedir ve kullanıcı kimlik doğrulaması, sunucu tarafı oluşturma, modeller ve formlarla çalışma, yönetim işlevleri ve web uygulamaları oluşturmanın düzinelerce diğer temel yönü için kutudan çıktığı gibi harika araçlar sağlar. Ancak, statik varlıkları ve medya dosyalarını işlemek için kullandığı araçlar, bence, ölçeklenebilir sitelerde üretim için pek uygun değil. Django çekirdek geliştiricileri, birçok insanın bu dosyaları üretimde işlemek için alternatif yaklaşımlar seçtiğini biliyor; çerçeve, yaptığınız zaman yolunuzdan çıkmakta çok iyidir. Genel kullanıma yönelik çoğu Django sitesi, statik varlıkları dahil etmek ve medya dosyalarını Django'ya özgü olmayan bu yaklaşımları kullanarak yönetmek isteyecektir.
Bir CDN'deki Statik Varlıklar
Küçük ve orta ölçekli projeler bir tane olmadan kurtulabilirken, bir CDN'nin (içerik dağıtım ağı) kullanımı kolaydır ve her boyuttaki uygulamanın performansını artırır. CDN, çoğunlukla statik varlıklar olmak üzere web içeriğini dağıtan ve sunan, genellikle dünya çapında bir sunucu ağıdır. Popüler CDN'ler arasında Cloudflare CDN, Amazon CloudFront ve Fastly bulunur. Bir CDN kullanmak için statik dosyalarınızı yüklersiniz, ardından uygulamanızda bunlara aşağıdaki şekilde başvurursunuz:
<link rel="stylesheet" type="text/css" href="https://cdn.example.com/path/to/your/files/app1/style.css">
Bu işlemin Django dağıtım komut dosyalarınızla entegre edilmesi kolaydır. python manage.py collectstatic
komutunu çalıştırdıktan sonra, oluşturulan dizini CDN'nize kopyalayın (kullandığınız hizmete göre büyük ölçüde değişen bir işlem), ardından statik varlıkları Django dağıtım paketinden kaldırın.
Geliştirme aşamasında, statik varlıklarınızın üretimdekinden farklı kopyalarına erişmek isteyeceksiniz. Bu sayede üretim alanını etkilemeden yerel olarak değişiklik yapabilirsiniz. Dosyaları teslim etmek için yerel varlıkları kullanabilir veya CDN'nin ikinci bir örneğini çalıştırabilirsiniz. Projenizi/settings.py'yi CDN_URL CDN_URL
bazı özel değişkenlerle yapılandırın ve geliştirme ve üretimde varlıkların doğru sürümünü kullandığınızdan emin olmak için bu değeri şablonlarınızda kullanın.
Son bir not, CSS ve JavaScript için birçok kitaplığın çoğu web sitesinin kullanabileceği ücretsiz CDN'lere sahip olmasıdır. Örneğin Bootstrap 4 veya underscore.js yüklüyorsanız, bu genel CDN'leri kullanarak kendi kopyanızı geliştirme aşamasında kullanma zahmetinden ve üretimde kendi kopyalarınızı sunma masrafından kurtulabilirsiniz.
Özel Dosya Deposu Olan Medya Dosyaları
Hiçbir üretim Django sitesi, kullanıcı dosyalarını siteyi çalıştıran sunucuda bir yerde basit bir /media/ klasöründe saklamamalıdır. İşte yapmamak için birçok nedenden üçü:
- Birden çok sunucu ekleyerek siteyi büyütmeniz gerekiyorsa, yüklenen dosyaları bu sunucular arasında kopyalamanın ve eşitlemenin bir yoluna ihtiyacınız vardır.
- Bir sunucu çökerse, kaynak kodu sürüm kontrol sisteminizde yedeklenir, ancak sunucunuzu bunu yapacak şekilde yapılandırmadığınız sürece medya dosyaları varsayılan olarak yedeklenmez, ancak bu çaba için özel bir sunucu kullanmanız daha iyi olur. dosya deposu.
- Kötü amaçlı etkinlik olması durumunda, kullanıcı tarafından yüklenen dosyaları uygulamayı çalıştıran sunucudan ayrı bir sunucuda tutmak biraz daha iyidir, ancak bu hiçbir şekilde kullanıcı tarafından yüklenen dosyaları doğrulama gereksinimini ortadan kaldırmaz.
Kullanıcı tarafından yüklenen dosyalarınızı depolamak için üçüncü bir tarafı entegre etmek gerçekten çok kolay. Modellerinizdeki FileField
s öğesinin upload_to
değerini kaldırmak veya değiştirmek ve birkaç ayarı yapılandırmak dışında kodunuzdaki hiçbir şeyi değiştirmeniz gerekmez. Örneğin, dosyalarınızı AWS S3'te depolamayı planlıyorsanız, dosyaları Google Cloud, Azure, Backblaze veya benzer rakip hizmetlerle depolama sürecine çok benzeyen aşağıdakileri yapmak istersiniz.
İlk olarak, boto3
ve django-storages
storages kitaplıklarını kurmanız gerekecek. Ardından, bu makalenin kapsamı dışında olan AWS üzerinde bir kova ve IAM rolü kurmanız gerekiyor, ancak burada talimatları görebilirsiniz. Tüm bunlar yapılandırıldıktan sonra, project/settings.py dosyanıza üç değişken eklemeniz gerekir:
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" AWS_STORAGE_BUCKET_NAME = "BUCKET_NAME" AWS_S3_REGION_NAME = "us-east-2"
Ek olarak, AWS paketinize kimlik bilgisi erişimi ayarlamanız gerekecektir. Bazı öğreticiler, ayarlar dosyanıza veya ortam değişkenleri olarak bir kimlik ve gizli anahtar eklemeyi gösterecek, ancak bunlar güvenli olmayan uygulamalardır. Bunun yerine, anahtarları burada açıklandığı gibi yapılandırmak için AWS CLI ile django-storages
kullanın. django-storages
belgeleri de ilginizi çekebilir.
Geliştirme veya test ortam dosyalarının gerçek kullanıcılardan gelen yüklemelerle karışmasını istemezsiniz. Bundan kaçınmak oldukça basittir: biri geliştirme için (veya her geliştirici için bir tane), biri test için ve diğeri üretim için olmak üzere birden çok kova ayarlayın. Ardından, tek yapmanız gereken ortam başına AWS_STORAGE_BUCKET_NAME
ayarını değiştirmektir ve artık hazırsınız.
Performans ve Kullanılabilirlik
Web sitenizin performansını ve güvenilirliğini etkileyen çok sayıda faktör vardır. Bunları yönetmek için hangi yaklaşımı benimserseniz kullanın, önemli olan statik ve medya dosyalarını değerlendirirken bazı önemli olanları burada bulabilirsiniz.
Maliyet
Dosyaları bir kullanıcıya sunmak iki nedenden dolayı maliyetlidir: depolama ve bant genişliği. Dosyaları sizin için depolaması için barındırma sağlayıcısına ödeme yapmanız gerekir, ancak aynı zamanda dosyaları sunmaları için onlara ödeme yapmanız gerekir. Bant genişliği, depolamadan önemli ölçüde daha pahalıdır (örneğin, AWS S3, depolama için gigabayt başına 2,3 sent ve yazma sırasında İnternet'e gigabayt veri aktarımı başına 9 sent ücret alır). S3 veya CDN gibi bir dosya deposunun ekonomisi, Dijital Okyanus damlacığı gibi genelleştirilmiş bir ana bilgisayarın ekonomisinden farklıdır. Pahalı dosyaları kendileri için tasarlanmış hizmetlere taşıyarak uzmanlaşma ve ölçek ekonomilerinden yararlanın. Ayrıca, birçok dosya deposu ve CDN ücretsiz planlar sunar, böylece bunları kullanmadan kaçabilecek kadar küçük olabilecek siteler bunun yerine bunu yapabilir ve herhangi bir ek altyapı maliyeti olmadan avantajlardan yararlanabilir.
Sıkıştırma ve Kod Dönüştürme
Fotoğraflar ve videolar gibi statik varlıkların neden olduğu sorunların çoğu, büyük dosyalar olmalarıdır. Doğal olarak, geliştiriciler bu dosyaları küçültmeye çalışarak bu sorunu giderir. İki genel kategoride sıkıştırma ve kod dönüştürme karışımı kullanarak bunu yapmanın birkaç yolu vardır: kayıpsız ve kayıplı. Kayıpsız sıkıştırma, varlıkların orijinal kalitesini korur ancak dosya boyutunda nispeten mütevazı azalmalar sağlar. Kayıplı sıkıştırma veya kayıplı bir biçime dönüştürme, orijinal yapaylığın kalitesinin bir kısmını kaybetme pahasına çok daha küçük dosya boyutlarına izin verir. Bunun bir örneği, videoyu daha düşük bir bit hızına dönüştürmektir. Ayrıntılar için video dağıtımını optimize etmeyle ilgili bu makaleye göz atın. Web üzerinden büyük dosyalar sunarken, bant genişliği hızları genellikle, kayıplı sıkıştırma gerektiren yüksek oranda sıkıştırılmış eserler sunmanızı gerektirir.
YouTube değilseniz, sıkıştırma ve kod dönüştürme anında gerçekleşmez. Statik varlıklar dağıtımdan önce uygun şekilde biçimlendirilmelidir ve kullanıcılarınızın medya dosyalarında yeterli sıkıştırmayı ve uygun biçimlendirmeyi sağlamak için kullanıcı yüklemelerinde temel dosya türü ve dosya boyutu kısıtlamaları uygulayabilirsiniz.
küçültme
JavaScript ve CSS dosyaları genellikle resimler kadar büyük olmasa da, genellikle daha az bayta sıkıştırmak için sıkıştırılabilirler. Bu işleme küçültme denir. Küçültme, dosyaların kodlamasını değiştirmez, bunlar hala metindir ve küçültülmüş bir dosyanın yine de orijinal dili için geçerli kod olması gerekir. Küçültülmüş dosyalar orijinal uzantılarını korur.
Küçültülmüş bir dosyada kaldırılan en önemli şey gereksiz boşluktur ve bilgisayarın bakış açısından CSS ve JavaScript'teki neredeyse tüm boşluklar gereksizdir. Küçültme şemaları ayrıca değişken adlarını kısaltır ve yorumları kaldırır.
Varsayılan olarak küçültme, kodu gizler; bir geliştirici olarak, yalnızca küçültülmemiş dosyalarla çalışmalısınız. Dağıtım işlemi sırasındaki bazı otomatik adımlar, dosyaları depolanmadan ve sunulmadan önce küçültmelidir. Üçüncü taraf bir CDN tarafından sağlanan bir kitaplık kullanıyorsanız, varsa o kitaplığın küçültülmüş sürümünü kullandığınızdan emin olun. HTML dosyaları küçültülebilir, ancak Django sunucu tarafı oluşturmayı kullandığından, bunu anında yapmanın işlem maliyeti, büyük olasılıkla sayfa boyutundaki küçük azalmadan daha ağır basacaktır.
Küresel Kullanılabilirlik
Komşunuza mektup göndermenin ülke çapında göndermekten daha az zaman alması gibi, yakındaki verileri iletmek de dünyanın her yerine göndermekten daha az zaman alır. Bir CDN'nin sayfa performansını iyileştirme yollarından biri, varlıkları dünyanın her yerindeki sunuculara kopyalamaktır. Ardından, bir müşteri bir istekte bulunduğunda, en yakın sunucudan (genellikle bir uç düğüm olarak adlandırılır) statik varlıkları alır ve bu da yükleme sürelerini azaltır. Django sitesiyle CDN kullanmanın avantajlarından biri, statik varlıklarınızın küresel dağıtımını kodunuzun küresel dağıtımından ayırmaktır.
İstemci Tarafı Önbelleğe Alma
Kullanıcınızın yakınındaki bir sunucuda statik bir dosyaya sahip olmaktan daha iyi ne olabilir? Statik dosyanın kullanıcınızın cihazında zaten kayıtlı olması! Önbelleğe alma, bir hesaplamanın veya isteğin sonuçlarının tekrar tekrar daha hızlı erişilebilmesi için saklanması işlemidir. Tıpkı bir CSS stil sayfasının bir CDN'de dünya çapında önbelleğe alınabilmesi gibi, sitenizden ilk kez bir sayfa yüklediğinde müşterinin tarayıcısında önbelleğe alınabilir. Ardından, stil sayfası sonraki isteklerde aygıtın kendisinde bulunur, böylece istemci daha az istekte bulunur, sayfa yükleme süresini iyileştirir ve bant genişliği kullanımını azaltır.
Tarayıcılar kendi önbelleğe alma işlemlerini gerçekleştirir, ancak siteniz yoğun trafikten hoşlanıyorsa, Django'nun önbellek çerçevesini kullanarak istemci tarafı önbelleğe alma davranışınızı optimize edebilirsiniz.
Sonuç olarak
Yine, yol gösterici felsefem, araçları en iyi oldukları şey için kullanmaktır. Yalnızca hafif statik varlıklara sahip tek sunuculu projeler ve küçük ölçeklenebilir dağıtımlar, Django'nun yerleşik statik varlık yönetimini kullanabilir, ancak çoğu uygulama varlıkları bir CDN üzerinden sunulmak üzere ayırmalıdır.
Projeniz herhangi bir gerçek kelime kullanımına yönelikse, medya dosyalarını Django'nun varsayılan yöntemiyle saklamayın, bunun yerine bir hizmet kullanın. İnternet ölçeğinde "yeterli trafiğin" nispeten küçük bir sayı olduğu yeterli trafikle, mimariye, geliştirme sürecine ve dağıtıma yönelik ek komplikasyonlar, bir sırasıyla statik ve medya dosyaları için ayrı CDN ve dosya depolama çözümü.
Önerilen Kaynaklar
- Bölüm 1: Kullanıcı Modelleri ve Kimlik Doğrulama
- Bölüm 2: Şablonlama Satırları Kurtarır
- Bölüm 3: Modeller, Yönetici ve İlişkisel Veritabanından Yararlanma