10 najczęstszych błędów popełnianych przez programistów Django
Opublikowany: 2022-03-11W tym samouczku przyjrzymy się niektórym typowym błędom, które często popełniają programiści Django, oraz sposobom ich uniknięcia. Ten samouczek jest przydatny, nawet jeśli jesteś doświadczonym programistą Django, ponieważ błędy, takie jak utrzymywanie zbyt dużych ustawień lub konflikty nazw w zasobach statycznych, nie ograniczają się tylko do nowych programistów, którzy po raz pierwszy zajmą się Django.
Django to darmowa platforma internetowa w języku Python o otwartym kodzie źródłowym, która pomaga rozwiązywać typowe wyzwania programistyczne i umożliwia tworzenie elastycznych, dobrze ustrukturyzowanych aplikacji. Django ma wiele nowoczesnych funkcji po wyjęciu z pudełka. Dla mnie osobiście Django był moim pierwszym wyborem, ponieważ narzędzia administracyjne, narzędzie do mapowania relacyjnego obiektów (ORM), routingu i szablonów, ponieważ aplikacje wymagają dużo pracy i chociaż lubię swoją pracę tak bardzo, jak każdy programista, chcę wydać jak najmniej czasu na te podstawowe powtarzalne zadania. Django pozwala to wszystko zrobić bez utraty elastyczności.
Zabójcza funkcja Django to potężny, konfigurowalny interfejs administratora, który tworzy się automatycznie (automagicznie?) ze schematu modeli i modeli panelu administracyjnego, dzięki czemu czujesz się jak czarodziej. Za pomocą interfejsu administratora użytkownik może skonfigurować wiele rzeczy, w tym listę kontroli dostępu (ACL), uprawnienia i działania na poziomie wiersza, filtry, zamówienia, widżety, formularze, dodatkowe pomocniki adresów URL i wszystko, co tylko możesz sobie wyobrazić. Uważam, że każda aplikacja wymaga panelu administracyjnego — jeśli jeszcze nie, to tylko kwestia czasu, kiedy będzie potrzebna Twoja podstawowa aplikacja. Z administratorem Django możesz szybko i elastycznie je utworzyć.
Django ma potężny ORM, który po wyjęciu z pudełka działa ze wszystkimi głównymi bazami danych. Ponieważ jest leniwy, trafia do Twojej bazy danych tylko wtedy, gdy jest potrzebny, w przeciwieństwie do innych ORM-ów. Obsługuje wszystkie główne instrukcje (i funkcje) SQL, których możesz użyć z kodu źródłowego Pythona i jest bardzo wygodny ze względu na funkcje Pythona.
Silnik szablonów Django jest jednocześnie bardzo elastyczny i potężny. Możesz używać wielu standardowych filtrów i tagów, a także tworzyć nowe niestandardowe filtry i tagi dla swojego projektu. Django obsługuje inne silniki szablonów, a także szablony Django i zapewnia API do łatwej integracji innych silników szablonów poprzez standardowe funkcje skrótów do przetwarzania szablonów.
Django ma wiele innych dużych funkcji, takich jak router URL, który może analizować przychodzące żądania i budować nowe adresy URL na podstawie schematu routera. Jako całość, framework Django jest przyjemnym doświadczeniem i kiedy potrzebujesz pomocy, po prostu przeczytaj dokumentację.
Błąd nr 1: Używanie środowiska Global System Python do zależności projektowych
Nie używaj globalnego środowiska Pythona do zależności projektowych, ponieważ może to powodować konflikty zależności. Python nie może jednocześnie używać wielu wersji pakietów. Może to stanowić problem, jeśli różne projekty wymagają różnych niekompatybilnych wersji tego samego pakietu.
Ten błąd jest zwykle popełniany przez nowych programistów Pythona i Django, którzy nie wiedzą o funkcjach izolacji środowiska Pythona.
Istnieje wiele sposobów na odizolowanie środowiska, ale najczęstsze to:
- virtualenv: pakiet Pythona, który generuje folder środowiska Python i zawiera skrypty do [dez]aktywacji środowiska i zarządzania zainstalowanymi pakietami Pythona w środowisku. To moja ulubiona metoda, ponieważ jest to najprostszy sposób wykonania pracy. Zazwyczaj tworzę środowisko blisko folderu projektu.
- virtualenvwrapper: pakiet Pythona, który instaluje się globalnie i udostępnia zestaw narzędzi do tworzenia/usuwania/aktywowania/itd. środowiska wirtualne. Wszystkie środowiska wirtualne są przechowywane w jednym folderze (który można nadpisać za pomocą zmiennej środowiskowej WORKON_HOME). Nie widzę żadnych korzyści z używania
virtualenvwrapperzamiastvirtualenv. - Maszyny wirtualne (VM): Nie ma większej izolacji niż cała maszyna wirtualna dedykowana dla Twojej aplikacji. Istnieje wiele narzędzi do wyboru, w tym VirtualBox (bezpłatny), VMware, Parallels i Proxmox (moje osobiste ulubione i ma bezpłatną wersję). W połączeniu z narzędziem do automatyzacji maszyn wirtualnych, takim jak Vagrant, może to być niezwykle wydajne rozwiązanie.
- Kontenery: W ciągu ostatnich kilku lat używałem Dockera w prawie każdym projekcie, zwłaszcza w każdym nowym projekcie, który zaczynam od zera. Docker to niesamowite narzędzie, które zapewnia wiele funkcji i ma wiele narzędzi innych firm do automatyzacji kontenerów. Posiada funkcję buforowania warstw, która sprawia, że odbudowa kontenerów jest niezwykle szybka. W kontenerach wykorzystuję globalne środowisko systemowe Python, ponieważ każdy kontener ma swój własny system plików, a projekty są izolowane na wysokim poziomie. Docker umożliwia nowym członkom zespołu szybsze rozpoczęcie pracy nad projektem, zwłaszcza jeśli mają doświadczenie w Dockerze.
Jeśli mnie pytasz, wolę pakiet virtualenv Python i kontenery Docker do izolacji i zarządzania zależnościami projektu.
Błąd nr 2: Nie przypinanie zależności projektu w pliku requirements.txt
Każdy nowy projekt w Pythonie powinien zaczynać się od pliku requirements.txt i nowego izolowanego środowiska. Zwykle instalujesz wszystkie pakiety przez pip/easy_install , ale nigdy nie zapomnij dodać ich również do pliku requirements.txt . Ułatwia to ( możliwe , że jest to bardziej odpowiednie) wdrożenie projektu na serwerach lub członkowi zespołu, aby zainicjować projekt na własnym komputerze.
Ponadto równie ważne jest przypięcie określonej wersji zależności w pliku requirements.txt . Zazwyczaj różne wersje pakietu udostępniają różne moduły, funkcje i parametry funkcji; nawet niewielka zmiana wersji w zależności może spowodować uszkodzenie pakietu. Jest to bardzo poważny problem, jeśli Twój projekt jest już uruchomiony i regularnie planujesz wdrożenia, ponieważ bez wersjonowania Twój system kompilacji zawsze zainstaluje najnowszą dostępną wersję pakietu.
Zawsze przypinaj swoje opakowania do produkcji! Osobiście używam bardzo fajnego narzędzia zwanego pip-tools, które mi w tym pomaga. Udostępnia zestaw narzędzi wiersza polecenia, które pomagają zarządzać zależnościami. Automatycznie generuje plik requirements.txt , który przypina nie tylko twoje zależności, ale całe drzewo zależności, które zawiera zależności twoich zależności.
Czasami chcesz zaktualizować tylko niektóre pakiety ze swojej listy zależności (na przykład tylko Django/Flask/dowolny framework lub narzędzie), jeśli użyłeś „pip freeze” nie wiesz, które zależności są dla jakich pakietów, więc nie można zaktualizować zależności. Jednak dzięki pip-tools automatycznie przypina pakiety w zależności od przypiętej zależności, więc automatycznie rozwiązuje, które pakiety wymagają aktualizacji. Jako bonus, wiesz dokładnie, który pakiet pochodzi z której zależności, dzięki temu, jak oznacza je komentarzami w pliku requirements.txt .
Aby zachować szczególną ostrożność, dobrym pomysłem jest utworzenie kopii zapasowej plików źródłowych zależności! Zachowaj kopię w swoim systemie plików, folderze zarządzanym przez Git, folderze S3, FTP, SFTP — gdziekolwiek, ale miej ją pod ręką. Zdarzały się przypadki, w których stosunkowo niewielki pakiet, który nie był umieszczony na liście, zepsuł dużą liczbę pakietów w npm. Pip zapewnia narzędzie do pobierania wszystkich wymaganych zależności jako pliki źródłowe, przeczytaj więcej, uruchamiając pip help download .
Błąd nr 3: Używanie funkcji Pythona w starym stylu zamiast widoków opartych na klasach
Czasami dobrym pomysłem jest użycie małej funkcji Pythona w pliku views.py aplikacji, szczególnie w przypadku testów lub widoków narzędzi, ale generalnie powinieneś używać widoków opartych na klasach (CBV) w swoich aplikacjach.
CBV to ogólne widoki, które zapewniają abstrakcyjne klasy implementujące typowe zadania tworzenia stron internetowych zbudowane przez profesjonalistów i obejmujące wszystkie typowe zachowania. Mają niesamowity ustrukturyzowany interfejs API i możesz wykorzystać wszystkie zalety programowania obiektowego podczas korzystania z CBV. Sprawia, że kod źródłowy jest bardziej przejrzysty i czytelny. Zapomnij o trudach używania standardowych funkcji widoku Django do tworzenia list, operacji CRUD, przetwarzania formularzy itp. Po prostu rozszerzasz odpowiedni CBV dla swojego widoku i nadpisujesz właściwości klasy lub funkcje (zwykle funkcja zwraca właściwość i możesz tam dodać dowolną logikę, co tworzy spaghetti z kodu źródłowego w przypadku używania funkcji widoku zamiast CBV), które konfigurują zachowanie widoku.
Na przykład możesz mieć różne domieszki w swoim projekcie, które zastępują podstawowe zachowania CBV w celu budowania kontekstów widoku, sprawdzania autoryzacji na poziomie wiersza, automatycznego budowania ścieżek szablonów ze struktury aplikacji, integrowania inteligentnego buforowania i nie tylko.
Zbudowałem pakiet o nazwie Django Template Names, który standaryzuje nazwy szablonów dla twoich widoków na podstawie nazwy aplikacji i nazwy klasy widoku. Używam go na co dzień i oszczędza mi dużo czasu na wymyślanie nazw. Po prostu umieść mixin w swoim CBV — class Detail(TemplateNames, DetailView): — i zacznie działać! Oczywiście możesz nadpisać moje funkcje i dodać szablony responsywne na urządzenia mobilne, różne szablony dla klientów użytkownika lub cokolwiek innego.
Błąd nr 4: Pisanie grubych poglądów i chudych modelek
Pisanie logiki aplikacji w widokach zamiast w modelach oznacza, że napisałeś kod, który należy do Twojego modelu w widoku, czyniąc go „grubym”, a model „chudym”.
Powinieneś pisać grube modele, chude widoki.
Podziel logikę na małe metody w swoich modelach. Dzięki temu możesz używać go wiele razy z wielu źródeł (interfejsu administratora, interfejsu użytkownika, punktów końcowych interfejsu API, wielu widoków) w kilku wierszach kodu zamiast kopiowania i wklejania ton kodu. Dlatego następnym razem, gdy będziesz wysyłać użytkownikowi wiadomość e-mail, rozszerz model o funkcję poczty e-mail, zamiast zapisywać tę logikę w kontrolerze.
Ułatwia to również testowanie kodu jednostkowego, ponieważ logikę wiadomości e-mail można testować w jednym miejscu, a nie wielokrotnie w każdym kontrolerze, w którym ma to miejsce.
Więcej o problemie przeczytasz w projekcie Django Best Practices. Rozwiązanie jest proste: Napisz grube modele i chude widoki, więc zróbmy to w następnym projekcie (lub zrefaktoryzuj bieżący).
Błąd nr 5: Ogromny, niemożliwy do zarządzania plik ustawień
Nawet nowy plik ustawień projektu Django ma wiele ustawień. W prawdziwym projekcie plik ustawień rozrasta się do ponad 700 linii konfiguracji i stanie się trudny w utrzymaniu, zwłaszcza gdy środowiska deweloperskie, produkcyjne i pomostowe wymagają niestandardowych konfiguracji.
Możesz podzielić plik konfiguracyjny ręcznie i stworzyć niestandardowe programy ładujące, ale chcę przedstawić ci ładny i dobrze przetestowany pakiet Pythona, Django Split Settings, którego jestem współautorem.

Pakiet udostępnia dwie funkcje — optional i include — które obsługują symbole wieloznaczne dla ścieżek i importują pliki konfiguracyjne w tym samym kontekście, ułatwiając budowanie konfiguracji przy użyciu zadeklarowanych wpisów konfiguracji we wcześniej załadowanych plikach. Nie wpływa to na wydajność Django i można go używać w dowolnym projekcie.
Sprawdź przykład minimalnej konfiguracji:
from split_settings.tools import optional, include include( 'components/base.py', 'components/database.py', 'components/*.py', # the project different envs settings optional('envs/devel/*.py'), optional('envs/production/*.py'), optional('envs/staging/*.py'), # for any local settings optional('local_settings.py'), )Błąd nr 6: aplikacja typu „wszystko w jednym”, zła struktura aplikacji i nieprawidłowe rozmieszczenie zasobów
Każdy projekt Django składa się z wielu aplikacji. W notacji Django aplikacja jest pakietem Pythona, który zawiera przynajmniej pliki __init__.py i models.py ; w najnowszych wersjach Django, models.py nie jest już wymagane. __init__.py wystarczy.
Aplikacje Django mogą zawierać moduły Pythona, moduły specyficzne dla Django (widoki, adresy URL, modele, administrator, formularze, tagi szablonów itp.), pliki statyczne, szablony, migracje baz danych, polecenia zarządzania, testy jednostkowe i inne. Aplikacje monolitowe należy podzielić na małe aplikacje wielokrotnego użytku, korzystając z prostej logiki. Powinieneś być w stanie opisać cały cel aplikacji w jednym lub dwóch krótkich zdaniach. Na przykład: „Pozwala użytkownikom na rejestrację i aktywację konta przez e-mail”.
Dobrym pomysłem jest wywołanie folderu project i umieszczenie aplikacji w project/apps/ . Następnie umieść wszystkie zależności aplikacji w ich własnych podfolderach.
Przykłady:
- Pliki statyczne:
project/apps/appname/static/appname/ - Tagi szablonów:
project/apps/appname/templatetags/appname.py - Pliki szablonów:
project/apps/appname/templates/appname/
Zawsze poprzedzaj nazwę aplikacji w podfolderach, ponieważ wszystkie foldery statyczne są scalane w jeden folder, a jeśli co najmniej dwie aplikacje mają plik js/core.js , ostatnia aplikacja w settings.INSTALLED_APPLICATIONS zastąpi poprzednie. Miałem kiedyś ten błąd w moim bieżącym projekcie i straciłem około sześciu godzin na debugowanie, dopóki nie zdałem sobie sprawy, że inny programista static/admin/js/core.js , ponieważ zespół implementował niestandardowy panel administracyjny SPA i nazwał swoje pliki w ten sam sposób.
Oto przykładowa struktura aplikacji portalu, która ma wiele zasobów i modułów Pythona.
root@c5b96c395cfb:/test# tree project/apps/portal/ project/apps/portal/ ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ ├── __init__.py │ └── update_portal_feeds.py ├── migrations │ └── __init__.py ├── models.py ├── static │ └── portal │ ├── css │ ├── img │ └── js ├── templates │ └── portal │ └── index.html ├── templatetags │ ├── __init__.py │ └── portal.py ├── tests.py ├── urls.py └── views.py 11 directories, 14 filesKorzystając z takiej struktury, możesz w każdej chwili wyeksportować aplikację do innego pakietu Pythona i użyć jej ponownie. Możesz nawet opublikować go w PyPi jako pakiet open source lub przenieść do innego folderu.
Otrzymasz taką strukturę projektu:
root@c5b96c395cfb:/test# tree -L 3 . ├── deploy │ ├── chef │ └── docker │ ├── devel │ └── production ├── docs ├── logs ├── manage.py ├── media ├── project │ ├── __init__.py │ ├── apps │ │ ├── auth │ │ ├── blog │ │ ├── faq │ │ ├── pages │ │ ├── portal │ │ └── users │ ├── conf │ ├── settings.py │ ├── static │ ├── templates │ ├── urls.py │ └── wsgi.py └── static └── admin ├── css ├── fonts ├── img └── js 25 directories, 5 filesW prawdziwym projekcie będzie to oczywiście bardziej złożone, ale ta struktura sprawia, że wszystko jest prostsze i czystsze.
Błąd nr 7: STATICFILES_DIRS i STATIC_ROOT zakłopotanie początkujących programistów Django
Pliki statyczne to zasoby, które nie zmieniają się podczas korzystania z aplikacji, np. JavaScript, CSS, obrazy, czcionki itp. W Django są one „gromadzone” tylko w publicznym katalogu podczas procesu wdrażania.
W trybie deweloperskim — python manage.py runserver — Django wyszukuje pliki statyczne, korzystając z ustawienia STATICFILES_FINDERS . Domyślnie próbuje znaleźć żądany plik statyczny w folderach wymienionych w ustawieniu STATICFILES_DIRS . W przypadku niepowodzenia Django próbuje znaleźć plik za pomocą django.contrib.staticfiles.finders.AppDirectoriesFinder , który przeszukuje folder static każdej zainstalowanej aplikacji w projekcie. Pozwala to na pisanie aplikacji wielokrotnego użytku, które są dostarczane z własnymi plikami statycznymi.
W środowisku produkcyjnym obsługujesz statystyki za pomocą samodzielnego serwera WWW, takiego jak Nginx. Serwer sieciowy nie wie nic o strukturze aplikacji projektu Django ani o folderach, w których są dystrybuowane Twoje pliki statyczne. Na szczęście Django udostępnia polecenie zarządzania collect static management.py python manage.py collectstatic , które przechodzi przez STATICFILES_FINDERS i kopiuje wszystkie pliki statyczne z aplikacji static foldery i foldery wymienione w STATICFILES_DIRS do katalogu określonego w ustawieniu STATIC_ROOT . Pozwala to na rozwiązywanie statycznych zasobów plików przy użyciu tej samej logiki, co serwer trybu deweloperskiego Django i posiada wszystkie statyczne pliki w jednym miejscu dla twojego serwera WWW.
Nie zapomnij uruchomić collectstatic w swoim środowisku produkcyjnym!
Błąd nr 8: Domyślne STATICFILES_STORAGE , Django Templates Loaders w produkcji
STATICFILES_STORAGE
Porozmawiajmy o zarządzaniu zasobami środowiska produkcyjnego. Możemy zapewnić najlepsze wrażenia użytkownika, jeśli zastosujemy zasadę „aktywa nigdy nie wygasają” (o której możesz przeczytać więcej tutaj). Oznacza to, że wszystkie nasze pliki statyczne powinny być buforowane przez przeglądarki internetowe przez tygodnie, miesiące, a nawet lata. Innymi słowy, Twoi użytkownicy powinni pobierać Twoje zasoby tylko raz!
To fajne i możemy to zrobić za pomocą kilku linii w konfiguracji Nginx dla naszego folderu plików statycznych, ale co z unieważnianiem pamięci podręcznej? Jeśli użytkownik pobierze nasze zasoby tylko raz, co się stanie, jeśli zaktualizujesz swoje logo, czcionki, kod JavaScript lub kolor tekstu dla pozycji w menu? Aby to ominąć, powinieneś generować unikalne adresy URL i nazwy plików dla naszych plików statycznych przy każdym wdrożeniu!
Możemy to zrobić po prostu, używając ManifestStaticFilesStorage jako STATICFILES_STORAGE (uwaga, haszowanie jest włączone tylko w trybie DEBUG=false ) i uruchamiając omówione powyżej polecenie zarządzania collectstatic . Spowoduje to zmniejszenie liczby żądań zasobów do witryny produkcyjnej i znacznie przyspieszy renderowanie witryny.
Buforowany moduł ładujący szablony Django
Kolejną fajną funkcją Django jest buforowany moduł ładujący szablony, który nie przeładowuje i nie analizuje plików szablonów przy każdym renderowaniu szablonu. Analiza szablonów jest bardzo kosztowną operacją i zużywa dużo zasobów. Domyślnie szablony Django są analizowane przy każdym żądaniu, ale jest to złe, zwłaszcza podczas produkcji, gdzie można przetworzyć tysiące żądań w krótkim czasie.
Zapoznaj się z sekcją konfiguracji cached.Loader , aby uzyskać dobry przykład i szczegółowe informacje, jak to zrobić. Nie używaj modułu ładującego w trybie programistycznym, ponieważ nie ładuje ponownie przeanalizowanych szablonów z systemu plików; przy każdej zmianie szablonu konieczne będzie ponowne uruchomienie projektu przy użyciu python manage.py startapp . Może to być denerwujące podczas programowania, ale jest idealne do środowiska produkcyjnego.
Błąd nr 9: czyste skrypty Pythona dla narzędzi lub skryptów
Django zapewnia bardzo przyjemną funkcję o nazwie Polecenia zarządzania. Po prostu używaj go zamiast wymyślać na nowo koła i pisać surowe skrypty Pythona dla narzędzi projektowych.
Sprawdź także pakiet Django Extensions, który jest zbiorem niestandardowych rozszerzeń dla Django. Może ktoś już zaimplementował twoje polecenia! Istnieje już wiele typowych poleceń zadań.
Błąd nr 10: wymyślanie koła na nowo
Django i Python mają tysiące gotowych do użycia rozwiązań. Wypróbuj Google, zanim napiszesz coś, co nie jest wyjątkowe; prawdopodobnie istnieje bogate w funkcje rozwiązanie, które już istnieje.
Po prostu spróbuj uprościć sprawę. Najpierw Google! Instaluj, konfiguruj, rozszerzaj i integruj ze swoim projektem, jeśli znajdziesz pakiet dobrej jakości, i oczywiście, jeśli masz szansę, weź udział w open source.
Na początek oto lista moich własnych publicznych pakietów dla Django:
- Django Macros URL ułatwia pisanie (i odczytywanie) wzorców adresów URL w aplikacjach Django za pomocą makr.
- Django Templates Names to mały dodatek, który pozwala łatwo ujednolicić nazwy szablonów CBV.
- django-split-settings pozwala organizować ustawienia Django w wielu plikach i katalogach. Łatwe zastępowanie i modyfikowanie ustawień. Użyj symboli wieloznacznych w ścieżkach plików ustawień i oznacz pliki ustawień jako opcjonalne.
Nie powtarzaj się (DRY)!
Bardzo lubię metodologię DRY; dlatego stworzyłem szkielet Django jako wygodne narzędzie, które ma kilka naprawdę fajnych funkcji po wyjęciu z pudełka:
- Obrazy platformy Docker do projektowania/produkcji, zarządzane przez docker-compose, co pozwala łatwo organizować listę kontenerów.
- Skrypt Simple Fabric do wdrożenia produkcyjnego.
- Konfiguracja pakietu Django Split Settings z ustawieniami dla źródeł podstawowych i lokalnych.
- Webpack zintegrowany z projektem - Tylko folder
distzostanie zebrany przez Django na poleceniecollectstatic. - Skonfigurowano wszystkie podstawowe ustawienia i funkcje Django, takie jak buforowane szablony Django w środowisku produkcyjnym, zaszyfrowane pliki statyczne, zintegrowany pasek narzędzi debugowania, rejestrowanie itp.
Jest to gotowy do użycia szkielet Django dla twojego następnego projektu od zera i miejmy nadzieję, że zaoszczędzi ci dużo czasu, uruchamiając twój projekt. Webpack ma minimalną podstawową konfigurację, ale ma również zainstalowany SASS, wstępnie skonfigurowany do obsługi plików .scss .
