I denne veiledningen vil vi se på noen vanlige feil som ofte blir gjort av Django-utviklere og måter å unngå dem. Denne opplæringen er nyttig, selv om du er en dyktig Django-utvikler fordi feil, som å opprettholde uhåndterlig store innstillinger eller navngi konflikter i statiske eiendeler, ikke bare er begrenset til at nye utviklere tar sitt første stikk mot Django.
Django er et gratis og åpen kildekode Python-nettrammeverk som løser vanlige utviklingsutfordringer og lar deg bygge fleksible, godt strukturerte applikasjoner. Django har mange moderne funksjoner ute av esken. For meg personlig gjorde funksjonene Admin, Object Relational Mapping (ORM), Routing og Templating Django til mitt førstevalg fordi applikasjoner krever mye arbeid, og mens jeg liker jobben min så mye som enhver utvikler kan, vil jeg bruke så lite tid som mulig på disse grunnleggende repetitive oppgavene. Django lar deg gjøre alt dette uten å gå på kompromiss med fleksibiliteten.
Djangos drapefunksjon er et kraftig konfigurerbart administrasjonsgrensesnitt som bygger automatisk (automatisk?) Fra modellene dine og systempanelmodellene, slik at du føler deg som en veiviser. Gjennom administratorgrensesnittet kan en bruker konfigurere mange ting, inkludert tilgangskontrollisten (ACL), tillatelser og handlinger på radnivå, filtre, ordrer, widgets, skjemaer, ekstra URL-hjelpere og alt annet du kan forestille deg. Jeg tror at hver applikasjon krever et administrasjonspanel - hvis ikke ennå, er det bare et spørsmål om tid til den grunnleggende applikasjonen din trenger en. Med Django admin kan du opprette en raskt og fleksibelt.
Django har en kraftig ORM som fungerer med alle store databaser ut av esken. Siden den er lat, treffer den bare databasen din når du trenger den, i motsetning til andre ORM-er. Den støtter alle viktige SQL-instruksjoner (og funksjoner) som du kan bruke fra Python-kildekoden, og føles veldig behagelig på grunn av Pythons funksjoner.
Djangos malmotor er veldig fleksibel og kraftig på samme tid. Du kan bruke mye standard filtre og koder samt lage dine nye tilpassede filtre og koder for prosjektet ditt. Django støtter andre malmotorer så vel som Django maler, og det gir en API for enkel integrering av andre malmotorer gjennom standard snarveisfunksjoner for malbehandling.
Django har mange andre store funksjoner som en URL-router som kan analysere innkommende forespørsler og bygge nye URL-er fra et ruterskjema. Som helhet er Django-rammeverket en hyggelig opplevelse, og når du trenger hjelp, er det bare å lese dokumentasjon .
Ikke bruk Pythons globale miljø for prosjektavhengigheter, siden det kan produsere avhengighetskonflikter. Python kan ikke bruke flere pakkeversjoner samtidig. Dette kan være et problem hvis forskjellige prosjekter krever forskjellige inkompatible versjoner av samme pakke.
Denne feilen blir vanligvis gjort av nye Python- og Django-utviklere som ikke vet om Pythons miljøisoleringsfunksjoner.
Det er mange måter å isolere miljøet på, men de vanligste måtene er:
virtualenvwrapper
i stedet for virtualenv
.Hvis du spør meg, foretrekker jeg virtualenv
Python-pakke og Docker-containere for isolering og administrasjon av prosjektavhengighet.
requirements.txt
FilHvert nye Python-prosjekt skal starte med et krav.txt fil og et nytt isolert miljø. Normalt installerer du alle pakker gjennom pip/easy_install
men glem aldri å legge dem til requirements.txt
filen også. Dette gjør det lettere ( mulig for å være mer hensiktsmessig) for å distribuere prosjektet ditt på servere, eller for at et teammedlem skal starte opp prosjektet på sin egen maskin.
I tillegg er det like viktig å pin den spesifikke versjonen av avhengighetene dine i requirements.txt
fil. Vanligvis gir forskjellige versjoner av en pakke forskjellige moduler, funksjoner og funksjonsparametere; selv en mindre versjonsendring i en avhengighet kan ødelegge pakken din. Dette er et veldig alvorlig problem hvis prosjektet ditt er live, og du har regelmessig planlagt distribusjoner siden byggesystemet alltid vil installere den nyeste tilgjengelige versjonen av pakken uten versjon.
Fest alltid pakkene dine for produksjon! Personlig bruker jeg et veldig fint verktøy som heter pip-verktøy som hjelper meg med å gjøre dette. Det gir et sett med kommandolinjeverktøy som hjelper deg med å administrere avhengighetene dine. Den genererer automatisk en requirements.txt
som knytter ikke bare avhengighetene dine, men hele avhengighetstreet ditt, som inkluderer avhengighetene til avhengighetene dine.
Noen ganger vil du bare oppdatere noen pakker fra avhengighetslisten din (for eksempel bare Django / Flask / ethvert rammeverk eller verktøy). Hvis du brukte 'pip fryse', vet du ikke hvilke avhengigheter som er for hvilke pakker, og så du kan ikke oppgradere en avhengighet. Med pip-verktøy fester det imidlertid automatisk pakkene, avhengig av hvilken avhengighet du festet, så det løser automatisk hvilke pakker som må oppdateres. Som en bonus vet du også nøyaktig hvilken pakke som kom fra hvilken avhengighet på grunn av hvordan den markerer dem med kommentarer i requirements.txt
fil.
For å være ekstra forsiktig er det en fin ide å sikkerhetskopiere avhengighetskildefilene dine også! Oppbevar en kopi i filsystemet, en Git-administrert mappe, S3-mappe, FTP, SFTP — hvor som helst, men ha den til stede. Det har vært tilfeller der en relativt liten pakke som ikke var oppført, brøt et stort antall pakker på npm . Pip gir nyttig verktøyet for nedlasting av alle nødvendige avhengigheter som kildefiler, les mer ved å kjøre pip help download
.
Noen ganger er det lurt å bruke en liten Python-funksjon i applikasjonens views.py
filen spesielt for tester eller verktøyvisninger, men generelt bør du bruke klassebaserte visninger (CBV) i applikasjonene dine.
CBV er generiske synspunkter som gir abstrakte klasser som implementerer vanlige webutviklingsoppgaver bygget av fagpersoner og dekker all vanlig atferd. De har en fantastisk strukturert API, og du kan bruke alle fordelene med objektorientert programmering når du bruker CBVer. Det gjør kildekoden mer tydelig og lesbar. Glem smerten ved å bruke Django standardvisningsfunksjoner for oppføringer, CRUD-operasjoner, skjemabehandling osv. Du utvider bare den passende CBV for visningen og overstyrer klasseegenskaper eller funksjoner (vanligvis returnerer en funksjon en egenskap, og du kan legge til hvilken som helst logikk der lager spaghetti fra kildekoden din i tilfelle du bruker visningsfunksjoner i stedet for CBVer) som konfigurerer visningsatferden.
For eksempel kan du ha forskjellige miksinger i prosjektet ditt som overstyrer grunnleggende CBV-atferd for å bygge visningssammenhenger, sjekke autorisasjon på radnivå, automatisk bygge malveier fra applikasjonsstrukturen, integrere smart caching og mer.
Jeg bygde pakken som heter Django malnavn , som standardiserer malnavn for visningene dine basert på et applikasjonsnavn og et visningsklassenavn. Jeg bruker den hver dag, og det sparer mye tid for å finne på navn. Bare sett mixin i CBV— class Detail(TemplateNames, DetailView):
—og den begynner å virke! Selvfølgelig kan du overstyre funksjonene mine og legge til mobilresponsive maler, forskjellige maler for brukeragenter eller noe annet du vil ha.
Å skrive applikasjonslogikken din i visninger i stedet for modeller betyr at du har skrevet kode som hører hjemme i modellen din i visningen, noe som gjør den 'feit' og modellen din 'tynn'.
Du bør skrive fete modeller, mager utsikt.
Bryt logikken i små metoder på modellene dine. Dette lar deg bruke det flere ganger fra flere kilder (grensesnitt for administrasjonsgrensesnitt, frontgrensesnitt, API-endepunkter, flere visninger) i noen få linjer med kode i stedet for å kopiere og lime inn tonnevis med kode. Så neste gang du sender en bruker en e-post, utvider du modellen med en e-postfunksjon i stedet for å skrive denne logikken i kontrolleren din.
Dette gjør også koden din enklere å teste enheten fordi du kan teste e-postlogikken på ett sted, i stedet for gjentatte ganger i hver kontroller der dette foregår.
Du kan lese mer om problemet i Beste fremgangsmåter for Django prosjekt. Løsningen er enkel: Skriv fete modeller og tynne visninger, så la oss gjøre det i ditt neste prosjekt (eller refaktorere det nåværende).
Selv det nye Django-prosjektets innstillingsfil har mange innstillinger. I et ekte prosjekt vokser en innstillingsfil til over 700 konfigurasjonslinjer og blir vanskelig å vedlikeholde, spesielt når utviklings-, produksjons- og iscenesettelsesmiljøene dine trenger tilpassede konfigurasjoner.
Du kan dele konfigurasjonsfilen manuelt og lage egendefinerte lastere, men jeg vil introdusere deg til en fin og velprøvd Python-pakke, Django Split innstillinger , som jeg har vært medforfatter på.
Pakken inneholder to funksjoner - optional
og include
—som støtter jokertegn for banene og importerer konfigurasjonsfilene dine i samme kontekst, noe som gjør det enkelt å bygge konfigurasjonen ved hjelp av erklærte konfigurasjonsoppføringer i tidligere lastede filer. Det påvirker ikke Django-ytelsen, og du kan bruke den i alle prosjekter.
Sjekk ut det minimale konfigurasjonseksemplet:
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'), )
Ethvert Django-prosjekt består av flere applikasjoner. I Django notasjon, en applikasjon er en Python-pakke som inneholder minst __init__.py
og models.py
filer; i de nyeste Django-versjonene, models.py
er ikke lenger nødvendig. __init__.py
er nok.
Django-applikasjoner kan inneholde Python-moduler, Django-spesifikke moduler (visninger, URL-er, modeller, admin, skjemaer, maletiketter osv.), statiske filer, maler, databasemigrasjoner, administrasjonskommandoer, enhetstester og mer. Du bør dele monolittapplikasjonene dine i små, gjenbrukbare applikasjoner ved hjelp av enkel logikk. Du skal kunne beskrive hele formålet med appen i en eller to korte setninger. For eksempel: 'Tillater brukere å registrere og aktivere kontoen sin via e-post.'
Det er lurt å ringe prosjektmappen project
og plasser applikasjoner i project/apps/
. Deretter plasserer du alle applikasjonsavhengigheter i sine egne undermapper.
Eksempler:
project/apps/appname/static/appname/
project/apps/appname/templatetags/appname.py
project/apps/appname/templates/appname/
Før alltid applikasjonsnavnet i undermappene fordi alle statiske mapper slås sammen i en mappe, og hvis to eller flere applikasjoner hadde js/core.js
filen, den siste applikasjonen i settings.INSTALLED_APPLICATIONS
vil overstyre de forrige. Jeg hadde en gang denne feilen i mitt nåværende prosjekt og mistet omtrent seks timer feilsøking til jeg innså at en annen utvikler hadde overstyrt static/admin/js/core.js
fordi teamet implementerte et tilpasset SPA-adminpanel og ga filene deres navnet på samme måte.
Her er eksempelstruktur for en portalapplikasjon som har mange ressurser og Python-moduler.
[email protected] :/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
Ved å bruke en slik struktur kan du når som helst eksportere applikasjonen til en annen Python-pakke og bruke den igjen. Du kan til og med publisere den i PyPi som en åpen kildekode-pakke, eller flytte den til en annen mappe.
Du vil ende opp med en prosjektstruktur som denne:
[email protected] :/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
I et ekte prosjekt vil det selvfølgelig være mer komplekst, men denne strukturen gjør ting enklere og renere.
STATICFILES_DIRS
og STATIC_ROOT
Forvirre nybegynner Django-utviklere
Statiske filer er eiendeler som ikke endres gjennom appens bruk, for eksempel JavaScript, CSS, bilder, skrifttyper osv. I Django blir de bare 'samlet' inn i en offentlig katalog under distribusjonsprosessen.
I utviklingsmodus— python manage.py runserver
—Django søker etter statiske filer ved hjelp av STATICFILES_FINDERS
innstilling. Som standard prøver den å finne den forespurte statiske filen i mapper som er oppført i STATICFILES_DIRS
innstilling. I tilfelle feil, Django prøver å finne filen ved hjelp av django.contrib.staticfiles.finders.AppDirectoriesFinder
, som ser i static
mappen til alle installerte applikasjoner i prosjektet. Dette gjør at du kan skrive gjenbrukbare applikasjoner som sendes med egne statiske filer.
I produksjonen serverer du statikken din ved hjelp av en frittstående webserver som Nginx. Webserveren vet ingenting om Django-prosjektets applikasjonsstruktur eller hvilke mapper de statiske filene dine distribueres i. Heldigvis gir Django deg samlekommandoen for statisk administrasjon python manage.py collectstatic
, som går gjennom STATICFILES_FINDERS
og kopierer alle statiske filer fra applikasjoner static
mapper og mapper oppført i STATICFILES_DIRS
i katalogen du angir i STATIC_ROOT
innstilling. Dette muliggjør oppløsning av statiske filressurser ved hjelp av samme logikk som Django utviklingsmodus-server, og har alle statiske filer på ett sted for webserveren din.
Ikke glem å løpe collectstatic
i produksjonsmiljøet ditt!
STATICFILES_STORAGE
, Django Templates Loaders in ProductionSTATICFILES_STORAGE
La oss snakke om kapitalforvaltning i produksjonsmiljøet. Vi kan gi den beste brukeropplevelsen hvis vi bruker en policy for 'eiendeler utløper aldri' (som du kan lese mer om her ). Det betyr at alle våre statiske filer burde caches av nettlesere i flere uker, måneder eller til og med år. Med andre ord, brukerne dine bør laste ned eiendelene dine bare en gang!
Det er kult, og vi kan gjøre det med få linjer i Nginx-konfigurasjon for mappen for statiske filer, men hva med cache-ugyldighet? Hvis brukeren bare laster ned eiendelene våre en gang, hva skjer hvis du oppdaterte logoen, skriftene, JavaScript eller tekstfargen for et element i en meny? For å omgå dette, bør du generere unike URL-er og filnavn for våre statiske filer ved hver distribusjon!
Vi kan gjøre det ganske enkelt ved å bruke ManifestStaticFiles Storage som STATICFILES_STORAGE
(vær forsiktig, hashing er bare aktivert i DEBUG=false
modus) og kjører collectstatic
ledelseskommandoen diskutert ovenfor. Dette vil redusere antall forespørsler om eiendeler til produksjonsnettstedet ditt og vil gjøre nettstedet ditt gjengitt mye raskere.
En annen kul Django-funksjon er den hurtigbufrede malinnlasteren, som ikke laster opp og analyserer malfiler på hver mal som gjengis. Malparsing er en veldig kostbar operasjon og bruker mange ressurser. Som standard blir Django-maler analysert på hver forespørsel, men dette er dårlig, spesielt under produksjon, hvor du kan behandle tusenvis av forespørsler på kort tid.
Sjekk ut cached.Loader
konfigurasjonsdelen for et godt eksempel og detaljer om hvordan du gjør dette. Ikke bruk lasteren i utviklingsmodus fordi den ikke laster opp analyserte maler fra filsystemet. du må starte prosjektet på nytt med python manage.py startapp
på hver malendring. Dette kan være irriterende under utviklingen, men det er perfekt for produksjonsmiljøet.
Django gir en veldig fin funksjon som heter Ledelseskommandoer . Bare bruk den i stedet for å finne opp hjul på nytt og skrive rå Python-skript for prosjektverktøyene dine.
Sjekk også ut Django Extensions pakke, som er en samling tilpassede utvidelser for Django. Kanskje noen allerede har implementert kommandoene dine! Det er allerede mange vanlige oppgavekommandoer.
Django og Python har tusenvis av klare til bruk-løsninger. Prøv Googling før du skriver noe som ikke er unikt; det er sannsynligvis en funksjonsrik løsning som allerede eksisterer.
Bare prøv å gjøre ting enkle. Google først! Installer, konfigurer, utvid og integrer i prosjektet ditt hvis du finner en pakke av god kvalitet, og selvfølgelig bidrar til åpen kildekode når du har en sjanse.
Til å begynne med er her en liste over mine egne offentlige pakker for Django:
Ikke gjenta deg selv (TØRK)!
Jeg liker virkelig TØRR metodikk; det er derfor jeg skapte Django skjelett som et praktisk verktøy som har noen virkelig pene funksjoner ut av esken:
dist
mappe blir samlet av Django på collectstatic
kommando.Det er en klar til bruk Django Skeleton for ditt neste prosjekt fra bunnen av, og forhåpentligvis vil du spare deg for mye tid ved å starte prosjektet. Webpack har minimal grunnleggende konfigurasjon, men den har også SASS installert forhåndskonfigurert for å håndtere .scss
filer.