Top 10 greșeli pe care le fac dezvoltatorii Django
Publicat: 2022-03-11În acest tutorial, vom analiza câteva greșeli comune care sunt adesea făcute de dezvoltatorii Django și modalități de a le evita. Acest tutorial este util chiar dacă sunteți un dezvoltator Django calificat, deoarece greșelile, cum ar fi menținerea unor setări necontrolat de mari sau conflictele de denumire în activele statice, nu se limitează doar la noii dezvoltatori care iau prima lovitură la Django.
Django este un cadru web Python gratuit și open source, care rezolvă util provocările comune de dezvoltare și vă permite să construiți aplicații flexibile și bine structurate. Django are o mulțime de caracteristici moderne din cutie. Pentru mine personal, funcțiile Admin, Object Relational Mapping Tool (ORM), Routing și Templating au făcut din Django prima mea alegere, deoarece aplicațiile necesită multă muncă și, deși îmi place munca mea la fel de mult pe cât ar putea orice dezvoltator, vreau să cheltuiesc cât mai puțin timp posibil pentru aceste sarcini repetitive de bază. Django vă permite să faceți toate acestea fără a compromite flexibilitatea.
Caracteristica ucigașă a Django este o interfață de administrare configurabilă puternică, care se construiește automat (în mod automat?) din schema modelelor tale și modelele panoului de administrare, făcându-te să te simți ca un vrăjitor. Prin interfața de administrare, un utilizator poate configura o mulțime de lucruri, inclusiv lista de control al accesului (ACL), permisiunile și acțiunile la nivel de rând, filtre, comenzi, widget-uri, formulare, ajutoare URL suplimentare și orice altceva vă puteți imagina. Cred că fiecare aplicație necesită un panou de administrare - dacă nu încă, este pur și simplu o chestiune de timp până când aplicația dvs. de bază are nevoie de unul. Cu Django admin, puteți crea unul rapid și flexibil.
Django are un ORM puternic care funcționează imediat cu toate bazele de date majore. Deoarece este leneș, îți accesează baza de date doar atunci când ai nevoie, spre deosebire de alte ORM-uri. Acceptă toate instrucțiunile (și funcțiile) SQL majore pe care le puteți utiliza din codul sursă Python și se simte foarte confortabil datorită caracteristicilor lui Python.
Motorul de șabloane Django este foarte flexibil și puternic în același timp. Puteți utiliza o mulțime de filtre și etichete standard, precum și de a crea noi filtre și etichete personalizate pentru proiectul dvs. Django acceptă alte motoare de șabloane, precum și șabloane Django și oferă un API pentru integrarea ușoară a altor motoare de șabloane prin funcții standard de comenzi rapide pentru procesarea șabloanelor.
Django are o mulțime de alte funcții mari, cum ar fi un router URL, care poate analiza cererile primite și poate construi URL-uri noi dintr-o schemă de router. În ansamblu, framework-ul Django este o experiență plăcută și ori de câte ori aveți nevoie de ajutor, citiți documentația.
Greșeala nr. 1: Utilizarea mediului Python al sistemului global pentru dependențe de proiect
Nu utilizați mediul global Python pentru dependențe de proiect, deoarece poate produce conflicte de dependență. Python nu poate folosi mai multe versiuni de pachete în același timp. Aceasta poate fi o problemă dacă proiecte diferite necesită versiuni diferite incompatibile ale aceluiași pachet.
Această greșeală este făcută de obicei de noii dezvoltatori Python și Django care nu știu despre caracteristicile de izolare a mediului Python.
Există o mulțime de moduri de a vă izola mediul, dar cele mai comune modalități sunt:
- virtualenv: Un pachet Python care generează un folder de mediu Python și are scripturi pentru [de]activarea mediului și gestionarea pachetelor Python instalate în mediu. Aceasta este metoda mea preferată pentru că este cea mai simplă modalitate de a face treaba. De obicei, creez mediul aproape de folderul proiectului.
- virtualenvwrapper: Un pachet Python care se instalează la nivel global și oferă un set de instrumente pentru crearea/ștergerea/activarea/etc. medii virtuale. Toate mediile virtuale sunt stocate într-un singur folder (care poate fi suprascris prin variabila de mediu WORKON_HOME). Nu văd niciun avantaj în utilizarea
virtualenvwrapper
în loc devirtualenv
. - Mașini virtuale (VM): Nu există o izolare mai mare decât o întreagă mașină virtuală dedicată aplicației dvs. Există o mulțime de instrumente din care să alegeți, inclusiv VirtualBox (gratuit), VMware, Parallels și Proxmox (preferatul meu personal și are o versiune gratuită). Combinată cu un instrument de automatizare VM precum Vagrant, aceasta poate fi o soluție extrem de puternică.
- Containere: În ultimii câțiva ani, am folosit Docker în aproape fiecare proiect, în special în fiecare proiect nou pe care îl pornesc de la zero. Docker este un instrument uimitor care oferă o mulțime de funcții și are o mulțime de instrumente terțe pentru automatizarea containerelor. Are o funcție de stocare în cache a straturilor care face reconstruirea containerelor extrem de rapidă. În containere, folosesc mediul global Python, deoarece fiecare container are propriul său sistem de fișiere și proiectele sunt izolate la nivel înalt. Docker permite noilor membri ai echipei să înceapă să lucreze la proiect mai repede, mai ales dacă au experiență în Docker.
Dacă mă întrebați pe mine, prefer pachetul virtualenv
Python și containerele Docker pentru izolarea și gestionarea dependenței de proiect.
Greșeala nr. 2: Nu fixarea dependențelor de proiect într-un fișier requirements.txt
Fiecare proiect Python nou ar trebui să înceapă cu un fișier requirements.txt și un nou mediu izolat. În mod normal, instalați toate pachetele prin pip/easy_install
, dar nu uitați să le adăugați și la fișierul requirements.txt
. Acest lucru face mai ușor ( posibil să fie mai adecvat) implementarea proiectului pe servere sau pentru un membru al echipei să pornească proiectul pe propria mașină.
În plus, este la fel de important să fixați versiunea specifică a dependențelor dvs. în fișierul requirements.txt
. De obicei, versiunile diferite ale unui pachet oferă module, funcții și parametri de funcție diferiți; chiar și o modificare minoră a versiunii într-o dependență vă poate rupe pachetul. Aceasta este o problemă foarte serioasă dacă proiectul dvs. este activ și aveți implementări programate în mod regulat, deoarece, fără versiune, sistemul dvs. de compilare va instala întotdeauna cea mai recentă versiune disponibilă a pachetului.
Fixați-vă întotdeauna pachetele pentru producție! Personal, folosesc un instrument foarte frumos numit pip-tools, care mă ajută să fac asta. Acesta oferă un set de instrumente de linie de comandă care vă ajută să vă gestionați dependențele. Acesta generează automat un requirements.txt
care fixează nu doar dependențele dvs., ci întregul arbore de dependență, care include dependențele dependențelor dvs.
Uneori, doriți să actualizați doar unele pachete din lista de dependențe (de exemplu, doar Django/Flask/orice cadru sau utilitar), dacă ați folosit „pip freeze” nu știți care dependențe sunt pentru ce pachete și, astfel, nu pot face upgrade la o dependență. Cu pip-tools, totuși, fixează automat pachetele în funcție de dependența pe care ați fixat-o, astfel încât rezolvă automat pachetele care trebuie actualizate. Ca bonus, știți și exact ce pachet provine din ce dependență, datorită modului în care îi marchează cu comentarii în fișierul requirements.txt
.
Pentru a fi mai precaut, este o idee bună să faceți și copii de rezervă ale fișierelor sursă de dependență! Păstrați o copie în sistemul dvs. de fișiere, un folder gestionat de Git, folder S3, FTP, SFTP, oriunde, dar aveți-l la îndemână. Au existat cazuri în care un pachet relativ minor care nu era listat a spart un număr mare de pachete pe npm. Pip oferă în mod util instrumentul pentru descărcarea tuturor dependențelor necesare ca fișiere sursă, citiți mai multe rulând pip help download
.
Greșeala nr. 3: Folosirea funcțiilor Python în stil vechi în loc de vizualizări bazate pe clasă
Uneori este o idee bună să utilizați o funcție Python mică în fișierul views.py
al unei aplicații, în special pentru teste sau vizualizări de utilitate, dar, în general, ar trebui să utilizați vizualizări bazate pe clasă (CBV) în aplicațiile dvs.
CBV-urile sunt vederi generice care oferă clase abstracte care implementează sarcini comune de dezvoltare web create de profesioniști și care acoperă toate comportamentele comune. Au un API structurat uimitor și puteți folosi toate avantajele programării orientate pe obiecte atunci când utilizați CBV-uri. Vă face codul sursă mai clar și mai lizibil. Uitați de durerea utilizării funcțiilor de vizualizare standard Django pentru listări, operațiuni CRUD, procesare formulare etc. Extindeți doar CBV-ul potrivit pentru vizualizarea dvs. și suprascrieți proprietățile sau funcțiile clasei (de obicei, o funcție returnează o proprietate și puteți adăuga orice logică acolo ce face spaghete din codul sursă în cazul utilizării funcțiilor de vizualizare în loc de CBV) care configurează comportamentul de vizualizare.
De exemplu, puteți avea diferite combinații în proiectul dvs. care suprascriu comportamentele de bază CBV pentru crearea contextelor de vizualizare, verificarea autorizației la nivel de rând, crearea automată a căilor de șablon din structura aplicației dvs., integrarea memoriei cache inteligente și multe altele.
Am construit pachetul numit Django Template Names, care standardizează numele șabloanelor pentru vizualizările dvs. pe baza unui nume de aplicație și a unui nume de clasă de vizualizare. Îl folosesc în fiecare zi și îmi economisește mult timp pentru a inventa nume. Pur și simplu puneți mixin-ul în CBV-ul dvs. class Detail(TemplateNames, DetailView):
- și va începe să funcționeze! Desigur, puteți suprascrie funcțiile mele și puteți adăuga șabloane mobile receptive, diferite șabloane pentru user-agents sau orice altceva doriți.
Greșeala nr. 4: Scrierea vederilor grase și modelelor slabe
Scrierea logicii aplicației dvs. în vederi în loc de modele înseamnă că ați scris cod care aparține modelului dvs. în vizualizare, făcându-l „gros” și modelul dvs. „slăbit”.
Ar trebui să scrieți modele grase, vederi slabe.
Împărțiți logica în metode mici pe modelele dvs. Acest lucru vă permite să îl utilizați de mai multe ori din mai multe surse (interfață de utilizare a interfeței de administrare, interfață de utilizare front-end, puncte finale API, vizualizări multiple) în câteva rânduri de cod în loc să copiați și lipiți tone de cod. Deci, data viitoare când trimiteți un e-mail unui utilizator, extindeți modelul cu o funcție de e-mail în loc să scrieți această logică în controlerul dumneavoastră.
Acest lucru face, de asemenea, testarea unitară a codului dvs., deoarece puteți testa logica e-mailului într-un singur loc, mai degrabă decât în mod repetat în fiecare controler unde are loc acest lucru.
Puteți citi mai multe despre problemă în proiectul Django Best Practices. Soluția este simplă: scrieți modele grase și vederi slabe, așa că haideți să o facem în următorul proiect (sau refactorizați-l pe cel actual).
Greșeala nr. 5: Un fișier de setări uriaș, imposibil de gestionat
Chiar și noul fișier de setări al proiectului Django are o mulțime de setări. Într-un proiect real, un fișier de setări crește la peste 700 de linii de configurare și va deveni dificil de întreținut, mai ales atunci când mediile dvs. de dezvoltare, producție și staging au nevoie de configurații personalizate.
Puteți împărți manual fișierul de configurare și puteți crea încărcătoare personalizate, dar vreau să vă prezint un pachet Python frumos și bine testat, Django Split Settings, pe care l-am coautor.

Pachetul oferă două funcții — optional
și include
— care acceptă metacaractere pentru căi și importă fișierele de configurare în același context, făcând simplă construirea configurației folosind intrările de configurare declarate în fișierele încărcate anterior. Nu afectează performanța Django și îl puteți folosi în orice proiect.
Consultați exemplul de configurare minimă:
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'), )
Greșeala nr. 6: aplicație all-in-one, structură proastă a aplicației și plasare incorectă a resurselor
Orice proiect Django constă din mai multe aplicații. În notația Django, o aplicație este un pachet Python care conține cel puțin fișiere __init__.py
și models.py
; în cele mai recente versiuni Django, models.py
nu mai este necesar. __init__.py
este suficient.
Aplicațiile Django pot conține module Python, module specifice Django (vizualizări, URL-uri, modele, admin, formulare, etichete șabloane etc.), fișiere statice, șabloane, migrări de baze de date, comenzi de management, teste unitare și multe altele. Ar trebui să vă împărțiți aplicațiile monolit în aplicații mici, reutilizabile, folosind o logică simplă. Ar trebui să puteți descrie întregul scop al aplicației într-una sau două propoziții scurte. De exemplu: „Permite utilizatorilor să se înregistreze și să își activeze contul prin e-mail.”
Este o idee bună să apelați proiectul folderului de project
și să plasați aplicații în project/apps/
. Apoi, plasați toate dependențele aplicației în propriile lor subdosare.
Exemple:
- Fișiere statice:
project/apps/appname/static/appname/
- Etichete de șablon:
project/apps/appname/templatetags/appname.py
- Fișiere șablon:
project/apps/appname/templates/appname/
Prefixați întotdeauna numele aplicației în subdirectoare, deoarece toate folderele statice sunt îmbinate într-un singur folder și, dacă două sau mai multe aplicații au avut un fișier js/core.js
, ultima aplicație din settings.INSTALLED_APPLICATIONS
va înlocui pe cele anterioare. Odată am avut această eroare în proiectul meu actual și am pierdut aproximativ șase ore de depanare până mi-am dat seama că un alt dezvoltator a înlocuit static/admin/js/core.js
deoarece echipa implementa un panou de administrare SPA personalizat și și-a numit fișierele în același mod.
Iată un exemplu de structură pentru o aplicație portal care are multe resurse și module Python.
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 files
Folosind o astfel de structură, puteți în orice moment să exportați aplicația într-un alt pachet Python și să o utilizați din nou. Puteți chiar să îl publicați în PyPi ca pachet open source sau să îl mutați într-un alt folder.
Veți ajunge cu o structură de proiect ca aceasta:
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 files
Într-un proiect real, desigur, va fi mai complex, dar această structură face lucrurile mai simple și mai curate.
Greșeala nr. 7: STATICFILES_DIRS
și STATIC_ROOT
dezvoltatorii Django începători
Fișierele statice sunt active care nu se modifică prin utilizarea aplicației, de exemplu, JavaScript, CSS, imagini, fonturi etc. În Django, acestea sunt doar „colectate” într-un director public în timpul procesului de implementare.
În modul de dezvoltare — python manage.py runserver
— Django caută fișiere statice utilizând setarea STATICFILES_FINDERS
. În mod implicit, încearcă să găsească fișierul static solicitat în folderele listate în setarea STATICFILES_DIRS
. În caz de eșec, Django încearcă să găsească fișierul folosind django.contrib.staticfiles.finders.AppDirectoriesFinder
, care caută în folderul static
al fiecărei aplicații instalate în proiect. Acest lucru vă permite să scrieți aplicații reutilizabile care sunt livrate cu propriile fișiere statice.
În producție, vă serviți statica folosind un server web autonom precum Nginx. Serverul web nu știe nimic despre structura aplicațiilor proiectului Django sau în ce foldere sunt distribuite fișierele dvs. statice. Din fericire, Django vă oferă comanda de colectare a managementului static python manage.py collectstatic
, care parcurge STATICFILES_FINDERS
și copiază toate fișierele statice din aplicațiile static
. folderele și folderele listate în STATICFILES_DIRS
în directorul pe care îl specificați în setarea STATIC_ROOT
. Acest lucru permite rezolvarea resurselor de fișiere statice folosind aceeași logică ca serverul în modul de dezvoltare Django și are toate fișierele statice într-un singur loc pentru serverul dvs. web.
Nu uitați să rulați collectstatic
în mediul dvs. de producție!
Greșeala nr. 8: STATICFILES_STORAGE
implicit, încărcătoare de șabloane Django în producție
STATICFILES_STORAGE
Să vorbim despre managementul activelor din mediul de producție. Putem oferi cea mai bună experiență de utilizare dacă folosim o politică „activele nu expiră niciodată” (despre care puteți citi mai multe aici). Înseamnă că toate fișierele noastre statice ar trebui să fie stocate în cache de browserele web timp de săptămâni, luni sau chiar ani. Cu alte cuvinte, utilizatorii ar trebui să vă descarce activele o singură dată!
Este grozav și putem face acest lucru cu câteva linii în configurația Nginx pentru folderul nostru de fișiere statice, dar cum rămâne cu invalidarea cache-ului? Dacă utilizatorul va descărca materialele noastre o singură dată, ce se întâmplă dacă ați actualizat sigla, fonturile, JavaScript sau culoarea textului pentru un articol dintr-un meniu? Pentru a ocoli acest lucru, ar trebui să generați adrese URL și nume de fișiere unice pentru fișierele noastre statice la fiecare implementare!
O putem face pur și simplu utilizând ManifestStaticFilesStorage ca STATICFILES_STORAGE
(ai grijă, hashing-ul este activat doar în modul DEBUG=false
) și rulând comanda collectstatic
management discutată mai sus. Acest lucru va reduce numărul de solicitări de active pentru site-ul dvs. de producție și va face site-ul dvs. să fie afișat mult mai rapid.
Încărcător de șabloane Django stocat în cache
O altă caracteristică grozavă Django este încărcătorul de șabloane din cache, care nu reîncarcă și nu analizează fișierele șablon la fiecare randare de șablon. Analiza șabloanelor este o operațiune foarte costisitoare și utilizează o mulțime de resurse. În mod implicit, șabloanele Django sunt analizate la fiecare cerere, dar acest lucru este rău, mai ales în timpul producției, unde puteți procesa mii de solicitări într-un interval scurt de timp.
Consultați secțiunea de configurare cached.Loader
pentru un exemplu bun și detalii despre cum să faceți acest lucru. Nu utilizați încărcătorul în modul de dezvoltare deoarece nu reîncarcă șabloanele analizate din sistemul de fișiere; va trebui să reporniți proiectul folosind python manage.py startapp
la fiecare modificare a șablonului. Acest lucru poate fi enervant în timpul dezvoltării, dar este perfect pentru mediul de producție.
Greșeala nr. 9: Scripturi Python pur pentru utilitare sau scripturi
Django oferă o caracteristică foarte frumoasă numită Comenzi de gestionare. Folosiți-l în loc să reinventați roțile și să scrieți scripturi brute Python pentru utilitatile dvs. de proiect.
De asemenea, consultați pachetul Django Extensions, care este o colecție de extensii personalizate pentru Django. Poate cineva a implementat deja comenzile tale! Există deja o mulțime de comenzi de sarcini comune.
Greșeala nr. 10: Reinventarea roții
Django și Python au mii de soluții gata de utilizare. Încercați să căutați pe Google înainte de a scrie ceva care nu este unic; probabil că există o soluție bogată în funcții care există deja.
Încearcă doar să faci lucrurile simple. Google mai întâi! Instalați, configurați, extindeți și integrați în proiectul dvs. dacă găsiți un pachet de bună calitate și, desigur, contribuiți la open source atunci când aveți ocazia.
Pentru început, iată o listă cu propriile mele pachete publice pentru Django:
- Adresa URL a macrocomenzilor Django facilitează scrierea (și citirea) modelelor URL în aplicațiile Django folosind macrocomenzi.
- Django Templates Names este un mic amestec care vă permite să standardizați cu ușurință numele șabloanelor CBV.
- django-split-settings vă permite să organizați setările Django în mai multe fișiere și directoare. Modificați și modificați cu ușurință setările. Folosiți caractere metalice în căile fișierelor de setări și marcați fișierele de setări ca opționale.
Nu te repeta (USCAT)!
Îmi place foarte mult metodologia DRY; de aceea am creat scheletul Django ca un instrument comod, care are câteva caracteristici foarte bune din cutie:
- Imagini Docker pentru dezvoltare/producție, gestionate de docker-compose, care vă permite să orchestrați cu ușurință o listă de containere.
- Script Fabric simplu pentru implementarea în producție.
- Configurare pentru pachetul Django Split Settings cu setări pentru sursele de bază și locale.
- Webpack integrat în proiect - Doar folderul
dist
va fi colectat de Django la comandacollectstatic
. - S-au configurat toate setările și funcțiile de bază Django, cum ar fi șabloanele Django care se pot stoca în cache în producție, fișierele statice cu hashing, bara de instrumente de depanare integrată, înregistrarea în jurnal etc.
Este un Django Skeleton gata de utilizat pentru următorul dvs. proiect de la zero și, sperăm, vă va economisi mult timp prin pornirea proiectului dvs. Webpack are o configurație de bază minimă, dar are și SASS instalat preconfigurat pentru a gestiona fișierele .scss
.