Najważniejsze cechy Django: walka o zasoby statyczne i pliki multimedialne (część 4)

Opublikowany: 2022-03-10
Szybkie podsumowanie ↬ Programiści i projektanci front-end tworzą niesamowite statyczne zasoby dla aplikacji internetowych. Dzisiaj skupiamy się na tym, co dzieje się po wprowadzeniu poprawki do stylu lub pięknej grafiki, którą właśnie ukończyłeś. Zbadamy również obsługę plików przesyłanych przez użytkowników, zwanych plikami multimedialnymi. Wspólnie opracujemy intuicję dla strategii dostępnych dla programistów Django w celu udostępniania tych plików użytkownikom na całym świecie w bezpieczny, wydajny i opłacalny sposób.

Strony internetowe Django zawierają wiele plików. To nie tylko kod źródłowy konfiguracji, modeli, widoków i szablonów, ale także statyczne zasoby: CSS i JavaScript, obrazy, ikony. Jakby tego było mało, czasami pojawiają się użytkownicy i chcą wgrać własne pliki do Twojej witryny. To wystarczy, aby każdy programista nie mógł uwierzyć. Pliki wszędzie!

W tym miejscu chciałbym móc powiedzieć (bez zastrzeżeń): „Nie martw się, Django cię wspiera!” Ale niestety, gdy mamy do czynienia ze statycznymi zasobami i plikami multimedialnymi, trzeba sobie poradzić z wieloma zastrzeżeniami.

Dzisiaj zajmiemy się przechowywaniem i udostępnianiem plików zarówno w przypadku wdrożeń jednoserwerowych, jak i skalowalnych, biorąc pod uwagę takie czynniki, jak kompresja, buforowanie i dostępność. Omówimy również koszty i korzyści związane z sieciami CDN i dedykowanymi rozwiązaniami do przechowywania plików.

Uwaga : To nie jest samouczek dotyczący wdrażania witryny Django na dowolnej platformie. Zamiast tego, podobnie jak inne artykuły z serii Django Highlights (patrz poniżej), jest on przeznaczony jako przewodnik dla programistów i projektantów front-end, aby zrozumieć inne części procesu tworzenia aplikacji internetowej. Dzisiaj skupiamy się na tym, co dzieje się po wprowadzeniu poprawki do stylu lub pięknej grafiki, którą właśnie ukończyłeś. Wspólnie opracujemy intuicję dla strategii dostępnych dla programistów Django w celu udostępniania tych plików użytkownikom na całym świecie w bezpieczny, wydajny i opłacalny sposób.

Poprzednie części z serii:

  • Część 1: Modele użytkownika i uwierzytelnianie
  • Część 2: Szablonowanie oszczędza wiersze
  • Część 3: Modele, administrator i wykorzystanie relacyjnej bazy danych
Więcej po skoku! Kontynuuj czytanie poniżej ↓

Definicje

Większość z tych terminów jest dość prosta, ale warto poświęcić chwilę na ustalenie wspólnego słownictwa na potrzeby tej dyskusji.

Trzy typy plików w działającej aplikacji Django to:

  1. Kod źródłowy
    Pliki Python i HTML utworzone za pomocą frameworka Django. Pliki te stanowią rdzeń aplikacji. Pliki kodu źródłowego są zazwyczaj dość małe, mierzone w kilobajtach.
  2. Pliki statyczne
    Nazywane również „zasobami statycznymi”, pliki te obejmują CSS i JavaScript, zarówno napisane przez programistę aplikacji, jak i biblioteki innych firm, a także pliki PDF, instalatory oprogramowania, obrazy, muzykę, filmy i ikony. Te pliki są używane tylko po stronie klienta. Pliki statyczne mają zakres od kilku kilobajtów CSS do gigabajtów wideo.
  3. Pliki medialne
    Każdy plik przesłany przez użytkownika, od zdjęć profilowych po dokumenty osobiste, nazywany jest plikiem multimedialnym. Pliki te muszą być bezpiecznie i niezawodnie przechowywane i pobierane dla użytkownika. Pliki multimedialne mogą mieć dowolny rozmiar, użytkownik może przesłać kilka kilobajtów zwykłego tekstu do kilku gigabajtów wideo. Jeśli znajdujesz się na drugim końcu tej skali, prawdopodobnie potrzebujesz bardziej specjalistycznej porady, niż jest w stanie dać ten artykuł.

Dwa typy wdrożeń Django to:

  1. Jeden serwer
    Jednoserwerowe wdrożenie Django jest dokładnie tym, na co wygląda: wszystko żyje na jednym serwerze. Ta strategia jest bardzo prosta i bardzo przypomina środowisko programistyczne, ale nie jest w stanie skutecznie poradzić sobie z dużym lub niespójnym natężeniem ruchu. Podejście z jednym serwerem ma zastosowanie tylko do projektów szkoleniowych lub demonstracyjnych, a nie do rzeczywistych aplikacji, które wymagają niezawodnego czasu pracy bez przestojów.
  2. Skalowalny
    Istnieje wiele różnych sposobów wdrożenia projektu Django, który umożliwia jego skalowanie w celu spełnienia wymagań użytkowników. Strategie te często obejmują uruchamianie i wyłączanie wielu serwerów oraz korzystanie z narzędzi, takich jak systemy równoważenia obciążenia i zarządzane bazy danych. Na szczęście na potrzeby tego artykułu możemy skutecznie wrzucić do tej kategorii wszystko, co bardziej skomplikowane niż wdrożenie na jednym serwerze.

Opcja 1: Domyślne Django

Małe projekty zyskują dzięki prostej architekturze. Domyślna obsługa zasobów statycznych i plików multimedialnych w Django jest po prostu prosta. Dla każdego masz folder główny, który przechowuje pliki i znajduje się tuż obok kodu źródłowego na serwerze. Prosty. Te foldery główne są generowane i zarządzane głównie przez konfigurację yourproject/settings.py .

Zasoby statyczne

Najważniejszą rzeczą do zrozumienia podczas pracy z plikami statycznymi w Django jest polecenie python manage.py collectstatic polecenie. To polecenie przechodzi przez folder statyczny każdej aplikacji w projekcie Django i kopiuje wszystkie zasoby statyczne do folderu głównego. Uruchomienie tego polecenia jest ważną częścią wdrażania projektu Django. Rozważ następującą strukturę katalogów:

 - 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 - ...

Przyjmij również następujące ustawienia w project/settings.py :

 STATIC_URL = "/static/" STATIC_ROOT = "/path/on/server/to/djangoproject/static"

Uruchomienie polecenia python manage.py collectstatic spowoduje utworzenie następującego folderu na serwerze:

 - /path/on/server/to/djangoproject/static - app1 - style.css - script.js - img.jpg - app2 - style.css - image.png

Zwróć uwagę, że w każdym folderze statycznym znajduje się inny folder z nazwą aplikacji. Ma to na celu zapobieganie konfliktom przestrzeni nazw po zebraniu plików statycznych; jak widać w powyższej strukturze plików, dzięki temu app1/style.css i app2/style.css są odrębne. Stąd aplikacja będzie szukała plików statycznych w tej strukturze w STATIC_ROOT podczas produkcji. W związku z tym należy odwoływać się do plików statycznych w następujący sposób w szablonie w app1/templates/ :

 {% load static %} <link rel="stylesheet" type="text/css" href="{% static "app1/style.css" %}">

Django automatycznie dowiaduje się, skąd pobrać plik statyczny w trakcie programowania, aby zamodelować to zachowanie, nie trzeba uruchamiać collectstatic podczas programowania.

Więcej szczegółów znajdziesz w dokumentacji Django.

Pliki medialne

Wyobraź sobie profesjonalną witrynę sieciową z bazą danych użytkowników. Każdy z tych użytkowników miałby powiązany profil, który mógłby zawierać między innymi obraz awatara i dokument CV. Oto krótki przykładowy model tej informacji:

 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)

Aby to zadziałało, potrzebujesz następujących opcji w project/settings.py , tak jak w przypadku zasobów statycznych:

 MEDIA_URL = "/media/" MEDIA_ROOT = "/path/on/server/to/media"

ImageField dziedziczy po FileField , więc ma te same parametry i możliwości. Oba pola mają opcjonalny argument upload_to , który pobiera ciąg będący ścieżką i dołącza go do MEDIA_ROOT w celu przechowywania pliku, który jest następnie dostępny przez tę samą ścieżkę nad MEDIA_URL . Argument upload_to może również przyjmować funkcję, która zwraca łańcuch, jak pokazano za pomocą funkcji avatar_path .

Pamiętaj, aby pominąć katalog plików multimedialnych i jego zawartość z kontroli wersji. Jego zawartość może powodować konflikty, gdy dwóch programistów testuje tę samą aplikację na różnych komputerach, i w przeciwieństwie do zasobów statycznych nie jest częścią wdrażalnej aplikacji Django.

Opcja 2: Django z usługami

Moją przewodnią filozofią jest używanie narzędzi do tego, w czym są najlepsi. Django to niesamowity framework, który zapewnia doskonałe narzędzia do uwierzytelniania użytkowników, renderowania po stronie serwera, pracy z modelami i formularzami, funkcjami administracyjnymi i dziesiątkami innych istotnych aspektów tworzenia aplikacji internetowych. Jednak jego narzędzia do obsługi statycznych zasobów i plików multimedialnych moim zdaniem nie są odpowiednie do produkcji w witrynach skalowalnych. Twórcy rdzenia Django zdają sobie sprawę, że wiele osób wybiera alternatywne podejścia do obsługi tych plików w środowisku produkcyjnym; framework bardzo dobrze radzi sobie z zejściem z drogi, kiedy to robisz. Większość witryn Django przeznaczonych do ogólnego użytku będzie chciała zawierać statyczne zasoby i obsługiwać pliki multimedialne przy użyciu tych niespecyficznych dla Django podejść.

Aktywa statyczne na CDN

Chociaż małe i średnie projekty mogą obejść się bez niego, CDN (sieć dostarczania treści) jest łatwa w użyciu i poprawia wydajność aplikacji dowolnej wielkości. CDN to sieć serwerów, ogólnie na całym świecie, która dystrybuuje i obsługuje treści internetowe, głównie statyczne. Popularne sieci CDN obejmują Cloudflare CDN, Amazon CloudFront i Fastly. Aby korzystać z CDN, przesyłasz swoje pliki statyczne, a następnie w swojej aplikacji odwołujesz się do nich w następujący sposób:

 <link rel="stylesheet" type="text/css" href="https://cdn.example.com/path/to/your/files/app1/style.css">

Ten proces można łatwo zintegrować ze skryptami wdrożeniowymi Django. Po uruchomieniu polecenia python manage.py collectstatic skopiuj wygenerowany katalog do swojej sieci CDN (proces, który różni się znacznie w zależności od używanej usługi), a następnie usuń statyczne zasoby z pakietu wdrożeniowego Django.

W fazie rozwoju będziesz chciał uzyskać dostęp do innych kopii swoich zasobów statycznych niż w środowisku produkcyjnym. W ten sposób możesz wprowadzać zmiany lokalnie bez wpływu na witrynę produkcyjną. Możesz użyć zasobów lokalnych lub uruchomić drugą instancję sieci CDN, aby dostarczyć pliki. Skonfiguruj yourproject/settings.py z pewną zmienną niestandardową, taką jak CDN_URL , i użyj tej wartości w szablonach, aby upewnić się, że używasz prawidłowej wersji zasobów w fazie rozwoju i produkcji.

Ostatnią uwagą jest to, że wiele bibliotek dla CSS i JavaScript ma darmowe CDN, z których może korzystać większość stron internetowych. Jeśli ładujesz, powiedzmy, Bootstrap 4 lub underscore.js, możesz pominąć kłopoty z używaniem własnej kopii w fazie rozwoju i koszt obsługi własnych kopii w produkcji za pomocą tych publicznych sieci CDN.

Pliki multimedialne z dedykowanym magazynem plików

Żadna produkcyjna witryna Django nie powinna przechowywać plików użytkownika w prostym folderze /media/ gdzieś na serwerze, na którym działa ta witryna. Oto trzy z wielu powodów, dla których nie należy:

  1. Jeśli chcesz skalować witrynę, dodając wiele serwerów, potrzebujesz jakiegoś sposobu kopiowania i synchronizowania przesłanych plików na tych serwerach.
  2. Jeśli serwer ulegnie awarii, kopia zapasowa kodu źródłowego zostanie utworzona w systemie kontroli wersji, ale pliki multimedialne nie są domyślnie archiwizowane, chyba że skonfigurowałeś tak serwer, ale w tym celu lepiej byłoby użyć dedykowanego magazyn plików.
  3. W przypadku złośliwej aktywności nieco lepiej jest przechowywać pliki przesłane przez użytkownika na oddzielnym serwerze niż ten, na którym działa aplikacja, chociaż w żaden sposób nie usuwa to wymogu sprawdzania poprawności plików przesłanych przez użytkownika.

Zintegrowanie strony trzeciej do przechowywania plików przesłanych przez użytkowników jest naprawdę łatwe. Nie musisz niczego zmieniać w swoim kodzie, może z wyjątkiem usunięcia lub zmodyfikowania wartości upload_to pola FileField w swoich modelach i skonfigurowania kilku ustawień. Na przykład, jeśli planujesz przechowywać pliki w AWS S3, powinieneś wykonać następujące czynności, które są bardzo podobne do procesu przechowywania plików w Google Cloud, Azure, Backblaze lub podobnych konkurencyjnych usługach.

Najpierw musisz zainstalować biblioteki boto3 i django-storages . Następnie musisz skonfigurować zasobnik i rolę uprawnień w AWS, co wykracza poza zakres tego artykułu, ale instrukcje znajdziesz tutaj. Po skonfigurowaniu tego wszystkiego musisz dodać trzy zmienne do swojego projektu/settings.py :

 DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" AWS_STORAGE_BUCKET_NAME = "BUCKET_NAME" AWS_S3_REGION_NAME = "us-east-2"

Dodatkowo musisz skonfigurować dostęp do danych logowania do swojego zasobnika AWS. Niektóre samouczki zademonstrują dodawanie identyfikatora i tajnego klucza do pliku ustawień lub jako zmiennych środowiskowych, ale są to niebezpieczne praktyki. Zamiast tego użyj django-storages z AWS CLI, aby skonfigurować klucze, jak opisano tutaj. Możesz być również zainteresowany dokumentacją django-storages .

Nie chcesz, aby tworzenie lub testowanie plików multimedialnych mieszało się z materiałami przesłanymi przez rzeczywistych użytkowników. Unikanie tego jest dość proste: skonfiguruj wiele zasobników, jeden do programowania (lub jeden dla każdego programisty), jeden do testowania i jeden do produkcji. Następnie wszystko, co musisz zmienić, to ustawienie AWS_STORAGE_BUCKET_NAME dla środowiska i gotowe.

Wydajność i dostępność

Istnieje wiele czynników, które wpływają na wydajność i niezawodność Twojej witryny. Oto kilka ważnych kwestii dotyczących plików statycznych i multimedialnych, które mają znaczenie niezależnie od podejścia do zarządzania nimi.

Koszt

Udostępnianie plików użytkownikowi kosztuje z dwóch powodów: pamięci masowej i przepustowości. Musisz zapłacić dostawcy hostingu za przechowywanie plików za Ciebie, ale musisz także zapłacić im za obsługę plików. Przepustowość jest znacznie droższa niż pamięć masowa (na przykład AWS S3 pobiera 2,3 centa za gigabajt za pamięć w porównaniu do 9 centów za gigabajt danych przesyłanych do Internetu w momencie pisania). Ekonomia magazynu plików, takiego jak S3 lub CDN, różni się od ekonomii uogólnionego hosta, takiego jak kropla Oceanu Cyfrowego. Skorzystaj ze specjalizacji i ekonomii skali, przenosząc drogie pliki do przeznaczonych dla nich usług. Co więcej, wiele magazynów plików i sieci CDN oferuje bezpłatne plany, więc witryny, które mogą być wystarczająco małe, aby uciec bez ich używania, mogą to zrobić i czerpać korzyści bez dodatkowych kosztów infrastruktury.

Kompresja i transkodowanie

Większość problemów powodowanych przez statyczne zasoby, takie jak zdjęcia i filmy, wynika z tego, że są to duże pliki. Oczywiście programiści rozwiązują ten problem, próbując zmniejszyć te pliki. Można to zrobić na kilka sposobów, używając kombinacji kompresji i transkodowania w dwóch ogólnych kategoriach: bezstratnej i stratnej. Kompresja bezstratna zachowuje pierwotną jakość zasobów, ale zapewnia stosunkowo niewielkie zmniejszenie rozmiaru pliku. Kompresja stratna lub transkodowanie do formatu stratnego pozwala na znacznie mniejsze rozmiary plików kosztem utraty części jakości oryginalnego artefaktu. Przykładem tego jest transkodowanie wideo do niższej przepływności. Aby uzyskać szczegółowe informacje, zapoznaj się z tym artykułem o optymalizacji dostarczania wideo. Podczas obsługiwania dużych plików przez Internet, prędkości przepustowości często wymagają obsługi wysoce skompresowanych artefaktów, wymagających kompresji stratnej.

Jeśli nie jesteś YouTube, kompresja i transkodowanie nie zachodzą w locie. Zasoby statyczne powinny być odpowiednio sformatowane przed wdrożeniem i można wymusić podstawowe ograniczenia dotyczące typów i rozmiarów plików przesyłanych przez użytkowników, aby zapewnić wystarczającą kompresję i odpowiednie formatowanie w plikach multimedialnych użytkowników.

Minifikacja

Chociaż pliki JavaScript i CSS zwykle nie są tak duże jak obrazy, często można je skompresować, aby zmieścić się w mniejszej liczbie bajtów. Ten proces nazywa się minifikacją. Minifikacja nie zmienia kodowania plików, nadal są tekstem, a zminifikowany plik nadal musi być prawidłowym kodem dla swojego oryginalnego języka. Zminimalizowane pliki zachowują swoje oryginalne rozszerzenia.

Najważniejszą rzeczą usuniętą w zminifikowanym pliku są niepotrzebne białe znaki, az punktu widzenia komputera prawie wszystkie białe znaki w CSS i JavaScript są niepotrzebne. Schematy minifikacji skracają również nazwy zmiennych i usuwają komentarze.

Minimalizacja domyślnie zaciemnia kod; jako programista powinieneś pracować wyłącznie z plikami niezminimalizowanymi. Niektóre automatyczne kroki podczas procesu wdrażania powinny minimalizować pliki przed ich przechowywaniem i udostępnianiem. Jeśli korzystasz z biblioteki udostępnionej przez CDN innej firmy, upewnij się, że korzystasz ze zminimalizowanej wersji tej biblioteki, jeśli jest dostępna. Pliki HTML można zminimalizować, ale ponieważ Django używa renderowania po stronie serwera, koszt przetwarzania w locie najprawdopodobniej przewyższyłby niewielki spadek rozmiaru strony.

Globalna dostępność

Tak jak wysłanie listu do sąsiada zajmuje mniej czasu niż wysłanie go przez cały kraj, tak samo przesłanie danych w pobliżu zajmuje mniej czasu niż na całym świecie. Jednym ze sposobów, w jaki CDN poprawia wydajność strony, jest kopiowanie zasobów na serwery na całym świecie. Następnie, gdy klient wysyła żądanie, otrzymuje statyczne zasoby z najbliższego serwera (często nazywanego węzłem brzegowym), zmniejszając czas ładowania. Jedną z zalet korzystania z CDN z witryną Django jest oddzielenie globalnej dystrybucji zasobów statycznych od globalnej dystrybucji kodu.

Buforowanie po stronie klienta

Co jest lepszego niż posiadanie statycznego pliku na serwerze w pobliżu użytkownika? Posiadanie pliku statycznego już zapisanego na urządzeniu użytkownika! Buforowanie to proces przechowywania wyników obliczeń lub żądania, dzięki czemu można do nich wielokrotnie szybciej uzyskiwać dostęp. Podobnie jak arkusz stylów CSS może być buforowany na całym świecie w sieci CDN, może być buforowany w przeglądarce klienta przy pierwszym załadowaniu strony z Twojej witryny. Następnie arkusz stylów jest dostępny na samym urządzeniu w kolejnych żądaniach, więc klient wysyła mniej żądań, skracając czas ładowania strony i zmniejszając wykorzystanie przepustowości.

Przeglądarki wykonują własne operacje buforowania, ale jeśli Twoja witryna ma duży ruch, możesz zoptymalizować zachowanie pamięci podręcznej po stronie klienta za pomocą frameworka pamięci podręcznej Django.

Na zakończenie

Ponownie, moją filozofią przewodnią jest używanie narzędzi do tego, w czym są najlepsi. Projekty jednoserwerowe i małe skalowalne wdrożenia z tylko lekkimi zasobami statycznymi mogą korzystać z wbudowanego zarządzania zasobami statycznymi Django, ale większość aplikacji powinna oddzielić zasoby, które mają być obsługiwane przez CDN.

Jeśli Twój projekt jest przeznaczony do użycia w jakikolwiek sposób, nie przechowuj plików multimedialnych za pomocą domyślnej metody Django, zamiast tego użyj usługi. Przy wystarczającym ruchu, gdzie „wystarczający ruch” jest stosunkowo niewielką liczbą w skali Internetu, dodatkowe komplikacje w architekturze, procesie rozwoju i wdrożeniu są więcej niż warte, jeśli chodzi o wydajność, niezawodność i oszczędności związane z używaniem oddzielne rozwiązanie CDN i przechowywanie plików odpowiednio dla plików statycznych i multimedialnych.

rekomendowane lektury

  • Część 1: Modele użytkownika i uwierzytelnianie
  • Część 2: Szablonowanie oszczędza wiersze
  • Część 3: Modele, administrator i wykorzystanie relacyjnej bazy danych