Sådan skriver du effektive visninger, modeller og forespørgsler i Django

Jeg kan godt lide Django. Det er en velovervejet og intuitiv ramme med et navn, jeg kan udtale højt. Du kan bruge den til hurtigt at få et projekt i weekendstørrelse op, og du kan også bruge det til at køre fuldblæste produktionsapplikationer i stor skala.

Jeg har gjort begge disse ting, og gennem årene har jeg opdaget, hvordan man bruger nogle af Djangos funktioner til maksimal effektivitet. Disse er:

  • Klassebaseret versus funktionsbaseret visning
  • Django modeller
  • Henter objekter med forespørgsler

Lad os se på, hvordan disse værktøjer giver dig mulighed for at oprette en performant Django-applikation, der er behagelig at bygge og vedligeholde.

Klassebaseret versus funktionsbaseret visning

Husk, at Django hele Python er under hætten. Når det kommer til visninger, har du to valg: visningsfunktioner (undertiden kaldet "funktionsbaserede visninger") eller klassebaserede visninger.

For mange år siden, da jeg først byggede ApplyByAPI, var den oprindeligt sammensat udelukkende af funktionsbaserede synspunkter. Disse tilbyder granulær kontrol og er gode til implementering af kompleks logik. Ligesom i en Python-funktion har du fuldstændig kontrol (på godt og ondt) over, hvad udsigten gør.

Men med stor kontrol kommer stort ansvar, og funktionsbaserede synspunkter kan være lidt kedelige at bruge. Du er ansvarlig for at skrive alle de nødvendige metoder for, at udsigten fungerer - det er det, der giver dig mulighed for at skræddersy din applikation fuldstændigt.

I tilfælde af ApplyByAPI var der kun et par få steder, hvor det niveau af skræddersyet funktionalitet virkelig var nødvendigt. Overalt ellers begyndte funktionsbaserede synspunkter at gøre mit liv sværere. At skrive, hvad der i det væsentlige er en brugerdefineret visning til run-of-the-mill-operationer som at vise data på en listside, blev kedeligt, gentaget og fejlbehæftet.

Med funktionsbaserede visninger skal du finde ud af, hvilke Django-metoder der skal implementeres for at håndtere anmodninger og videregive data til visninger. Enhedstest kan tage noget arbejde at skrive. Kort sagt kræver den granulære kontrol, som funktionsbaserede visninger tilbyder, også noget granulært tedium til korrekt implementering.

Jeg endte med at holde ApplyByAPI tilbage, mens jeg omformulerede størstedelen af ​​synspunkterne til klassebaserede synspunkter. Dette var ikke en lille smule arbejde og refactoring, men da det var gjort, havde jeg en masse små udsigter, der gjorde en enorm forskel. Jeg mener, se bare på denne:

class ApplicationsList(ListView): model = Application template_name = "applications.html" 

Det er tre linjer. Min udviklerergonomi og mit liv blev meget lettere.

Du kan tænke på klassebaserede visninger som skabeloner, der dækker det meste af den funktionalitet, som enhver app har brug for. Der er visninger til visning af lister over ting, til visning af en ting i detaljer og redigering af visninger til udførelse af CRUD-handlinger (Opret, læs, opdater, slet).

Fordi implementeringen af ​​en af ​​disse generiske synspunkter kun tager et par linjer kode, blev min applikationslogik dramatisk kortfattet. Dette gav mig mindre gentagen kode, færre steder for noget at gå galt og en mere håndterbar applikation generelt.

Klassebaserede visninger er hurtige at implementere og bruge. De indbyggede klassebaserede generiske visninger kan kræve mindre arbejde for at teste, da du ikke behøver at skrive tests til den grundvisning Django giver. (Django laver sine egne tests for det; intet behov for din app at dobbelttjekke.)

For at tilpasse en generisk visning til dine behov kan du underklasse en generisk visning og tilsidesætte attributter eller metoder. I mit tilfælde, da jeg kun havde brug for at skrive tests til eventuelle tilpasninger, jeg tilføjede, blev mine testfiler dramatisk kortere, ligesom den tid og ressourcer, det tog at køre dem, blev.

Når du vejer valget mellem funktionsbaseret eller klassebaseret visning, skal du overveje omfanget af tilpasning, som visningen har brug for, og det fremtidige arbejde, der er nødvendigt for at teste og vedligeholde det.

Hvis logikken er almindelig, kan du muligvis ramme jorden med en generisk klassebaseret visning. Hvis du har brug for tilstrækkelig granularitet til, at omskrivning af en basisvisnings metoder ville gøre det for kompliceret, skal du i stedet overveje en funktionsbaseret visning.

Django modeller

Modeller organiserer din Django-applikations centrale koncepter for at gøre dem fleksible, robuste og nemme at arbejde med. Hvis de bruges klogt, er modeller en stærk måde at samle dine data på i en endelig kilde til sandhed.

Ligesom visninger leverer Django nogle indbyggede modeltyper til bekvemmelighed ved implementering af grundlæggende godkendelse, herunder bruger- og tilladelsesmodeller. For alt andet kan du oprette en model, der afspejler dit koncept ved at arve fra en overordnet modelklasse.

class StaffMember(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) company = models.OneToOneField(Company, on_delete=models.CASCADE) def __str__(self): return self.company.name + " - " + self.user.email 

Når du opretter en brugerdefineret model i Django, underklasserer du Djangos modelklasse og drager fordel af al dens magt. Hver model, du opretter, kortlægges generelt til en databasetabel. Hver attribut er et databasefelt. Dette giver dig mulighed for at skabe objekter til at arbejde med, som mennesker bedre kan forstå.

Du kan gøre en model nyttig for dig ved at definere dens felter. Mange indbyggede felttyper leveres bekvemt. Disse hjælper Django med at finde ud af datatypen, HTML-widgeten, der skal bruges til gengivelse af en formular, og endda formvalideringskrav. Hvis det er nødvendigt, kan du skrive tilpassede modelfelter.

Databaseforhold kan defineres ved hjælp af et ForeignKey-felt (mange-til-en) eller et ManyToManyField (giver dig tre gæt). Hvis disse ikke er tilstrækkelige, er der også et OneToOneField.  

Together, these allow you to define relations between your models with levels of complexity limited only by your imagination. (Depending on the imagination you have, this may or may not be an advantage.)

Retrieving objects with queries

Use your model’s Manager (objects by default) to construct a QuerySet. This is a representation of objects in your database that you can refine, using methods, to retrieve specific subsets. All available methods are in the QuerySet API and can be chained together for even more fun.

Post.objects.filter( type="new" ).exclude( title__startswith="Blockchain" ) 

Some methods return new QuerySets, such as filter(), or exclude(). Chaining these can give you powerful queries without affecting performance, as QuerySets aren’t fetched from the database until they are evaluated. Methods that evaluate a QuerySet include get(), count(), len(), list(), or bool().

Iterating over a QuerySet also evaluates it, so avoid doing so where possible to improve query performance. For instance, if you just want to know if an object is present, you can use exists() to avoid iterating over database objects.

Use get() in cases where you want to retrieve a specific object. This method raises MultipleObjectsReturned if something unexpected happens, as well as the DoesNotExist exception, if, take a guess.

Hvis du gerne vil hente et objekt, der muligvis ikke findes i sammenhæng med en brugers anmodning, skal du bruge det bekvemme get_object_or_404()eller get_list_or_404()som rejser i Http404stedet for DoesNotExist. Disse nyttige genveje passer til netop dette formål. For at oprette et objekt, der ikke eksisterer, er der også det praktiske get_or_create().

Effektive væsentlige ting

Du har nu styr på disse tre vigtige værktøjer til at opbygge din effektive Django-applikation - tillykke!

Der er meget mere, som Django kan gøre for dig, så hold øje med fremtidige artikler.

Hvis du vil bygge videre på GitHub, kan du måske oprette min django-sikkerhedskontrol GitHub Action. I mellemtiden er du godt på vej til at opbygge et smukt softwareprojekt.