Pydantic är ett kraftfullt bibliotek för datavalidering och parsing, som skiljer sig från andra liknande bibliotek genom att erbjuda en basmodell (BaseModel) som möjliggör validering genom arv. När man bygger en användarmodell, är det viktigt att definiera de grundläggande uppgifterna som ska associeras med användaren. De mest grundläggande attributen inkluderar användarnamn, e-postadress, ID och födelsedatum. För att skapa en användarmodell baserat på dessa krav i Pydantic kan det se ut på följande sätt:
Denna modell hanterar validering och parsing direkt vid instansiering, vilket gör att ingen ytterligare validering behövs när man skapar en användare. Om man försöker skapa en användare med felaktig data kommer Pydantic automatiskt att informera om valideringsfel. Ett exempel på detta är när man försöker skapa en användare med ett ID som inte är ett heltal:
Resultatet blir ett detaljerat felmeddelande som förklarar att ID:t borde vara ett giltigt heltal. En av de stora fördelarna med Pydantic är att den fortsätter att validera resten av instansen, även om den stöter på ett fel, vilket gör att alla fel kan fångas och hanteras på en gång. Detta beteende är särskilt användbart i API-sammanhang där man kan returnera alla fel som en användare har skickat in i ett enda svar, till exempel i JSON-format.
Förutom grundläggande datavalidering tillhandahåller Pydantic också funktioner som deserialisering, serialisering och modifiering av data. Dessa funktioner är nödvändiga för att kunna bearbeta och överföra data mellan system på ett strukturerat sätt.
Deserialisering, som refererar till att mata in data i modellen, är nära kopplad till validering. När man instansierar en Pydantic-modell sker både validering och parsing. Om man vill skicka in data som ett dictionary, kan man använda metoden model_validate() för att validera och skapa en instans av modellen på en gång:
Här ser man att model_validate() accepterar en Python-dictionary och returnerar en instans av modellen efter att ha utfört validering av datatyperna. Pydantic erbjuder också en metod för att skapa instanser utan att validera data, model_construct(), men denna bör användas med försiktighet, eftersom den kringgår valideringsprocessen.
En annan viktig aspekt är fältens hantering i Pydantic-modeller. Fälten kan vara obligatoriska, nullable eller ha fördefinierade värden. Detta gör det enkelt att skapa modeller som passar specifika krav. Till exempel kan ett användarkonto ha olika typer av värden (t.ex. "personal" eller "business"), eller så kan det vara None, vilket gör det flexibelt att hantera olika användartyper.
I detta exempel definieras ett fält account som endast kan ha värdena "personal" eller "business", och ett nickname som kan vara antingen en sträng eller None. Pydantic tillhandahåller också möjligheten att inspektera modellens fält med hjälp av model_fields-egenskapen, vilket gör det lätt att få en översikt över modellens struktur.
När det gäller att använda Pydantic i praktiken, är det viktigt att förstå att den standardmässigt arbetar i en "lax" läge, vilket innebär att den försöker omvandla de angivna typerna till de deklarerade typerna i modellen. Om du till exempel skickar in användarens ID som en sträng, kommer Pydantic att konvertera den till ett heltal utan att ge ett felmeddelande.
Även om det är möjligt att modifiera fälten direkt via punktnotation, som user.id = "five", är det inte rekommenderat, eftersom detta omgår valideringsreglerna. Det är bäst att undvika att direkt modifiera fälten för att säkerställa att alla regler för datavalidering upprätthålls.
Pydantic är därför ett kraftfullt verktyg för att skapa robusta, validerade användarmodeller som gör det enkelt att hantera indata och utdata på ett konsekvent sätt. Det ger både flexibilitet och säkerhet, vilket gör det till ett oumbärligt verktyg när man arbetar med data och API:er i Python.
Hur hanterar FastAPI HTTP-statuskoder och felmeddelanden i API:er?
FastAPI, som en modern webbapplikationsram, betonar vikten av att noggrant hantera HTTP-statuskoder och svar. Statuskoder är en grundläggande del av att definiera kommunikation mellan klient och server. Dessa koder ger direkt och tydlig information om resultatet av en begäran, vare sig det handlar om ett lyckat svar, ett fel eller en omdirigering. Genom att använda FastAPI kan utvecklare på ett enkelt sätt anpassa och specificera dessa statuskoder för olika scenarier.
Vid en vanlig GET-begäran till FastAPI-rotvägen kommer ett svar som kan liknas vid detta:
Här används statuskoden 208 Already Reported, som indikerar att begäran redan har rapporterats och inget ytterligare åtgärd krävs. Det är viktigt att förstå att FastAPI gör det möjligt att definiera egna statuskoder för olika HTTP-metoder, såsom 200 (OK) för framgångsrika operationer, 204 (No Content) för borttagning av objekt, och 201 (Created) för skapande av objekt. Användningen av korrekta statuskoder förbättrar API:ets användarvänlighet och följer etablerade webbestämmelser.
Vidare kan FastAPI även utnyttja Pydantic, som gör det möjligt att skapa modeller för svaren från API:et. Genom att använda argumentet response_model kan utvecklare specificera vilka fält som ska inkluderas i svaret. Detta tillåter utvecklare att inte bara kontrollera hur begärningar formuleras utan även hur svaren struktureras och filtreras innan de skickas till klienten.
FastAPI är också mycket flexibel när det gäller anpassning av svar. Medan FastAPI inte tillhandahåller en inbyggd metod för att direkt anpassa hela svaret, är det mycket enkelt att modifiera och sätta HTTP-huvuden och cookies. Genom att använda standard HTTP-åtgärder kan utvecklare anpassa det som skickas tillbaka till klienten, exempelvis genom att justera statuskoden, sätta egna rubriker eller skicka cookies. Dessutom går det utmärkt att returnera svar i olika format, såsom HTML, strömmade filer eller till och med omdirigeringar.
När det gäller felhantering i FastAPI måste detta göras med noggrant definierade HTTP-statuskoder. Fel är ofrånkomliga i alla applikationer, och användare kan oavsiktligt skicka felaktiga parametrar eller ofullständiga data i en begäran. För att hantera dessa situationer är det viktigt att snabbt identifiera problemen och ge användarna informativa och hjälpsamma felmeddelanden.
FastAPI använder sig av en exceptionklass som kallas HTTPException, som gör det möjligt att definiera egna felmeddelanden och statuskoder. Här är ett exempel på hur detta kan tillämpas:
I detta exempel kastar API:et en 406 Not Acceptable-felkod om användaren försöker lägga till en bil som ännu inte har tillverkats (dvs. med ett årtal som är högre än 2022). Det är denna form av anpassad felhantering som gör FastAPI så kraftfullt och flexibelt för utvecklare.
En viktig aspekt av FastAPI som förenklar kodhantering är systemet för beroendeinjektion (Dependency Injection, DI). DI gör det möjligt att dela funktionalitet som databasanslutningar, autentisering eller andra gemensamma tjänster mellan olika API-endpoints. Istället för att skriva samma kod på flera ställen i applikationen, kan en funktion skapas som hanterar logiken, och sedan kan denna funktion användas på olika delar av API:et genom att skicka den som ett argument i en path-operation.
FastAPI:s DI-system förenklar också användningen av autentisering, eftersom du kan definiera en gemensam autentiseringstjänst och använda den på alla rutter som kräver att användaren är inloggad. Detta är ett kraftfullt verktyg, särskilt när du bygger komplexa applikationer där flera resurser behöver ha liknande säkerhetskrav.
En annan användbar funktion i FastAPI är APIRouter-modulen, som gör det möjligt att organisera och strukturera stora API:er på ett effektivt sätt. Istället för att samla alla endpoints i en enda stor fil, kan du använda APIRouter för att gruppera relaterade rutter och resurser i separata moduler. På detta sätt kan varje resurs (t.ex. användare eller bilar) hanteras separat, vilket gör koden mer modulär och lättare att underhålla.
Exempel på en sådan uppdelning kan vara:
Genom att använda denna struktur kan du skapa ett API där varje resurs får sitt eget routerobjekt, vilket gör det lättare att hålla koden organiserad och skalbar. Detta är särskilt viktigt när projektet växer och flera utvecklare är involverade.
För att sammanfatta, FastAPI är en mycket kraftfull och flexibel ram för att bygga moderna webbtjänster. Genom att utnyttja HTTP-statuskoder, anpassade felmeddelanden, beroendeinjektion och modulär kodstruktur kan du bygga pålitliga och lättunderhållna API:er. Det är också värt att notera att även om JSON är det vanligaste formatet för svar, kan FastAPI även användas för att generera andra typer av svar som HTML, strömmande data eller omdirigeringar.
Hur skapar man en enkel routerstruktur med React Router och hanterar sidinnehåll?
För att skapa en navigerbar applikation i React krävs en routerstruktur som gör det möjligt att hantera olika vägar (routes) utan att ladda om hela sidan. Detta kan göras effektivt med React Router, som tillhandahåller ett sätt att länka samman komponenter med specifika vägar och skapa dynamisk sidnavigering.
En av de första sakerna att notera är att när vi använder React Router måste vi definiera våra vägar genom att skapa ett routerobjekt och använda en funktion som heter createRoutesFromElements. Denna funktion gör det möjligt att definiera en uppsättning av rutter som sedan mappas till specifika komponenter. En route definieras genom att ange en väg och sedan koppla den till en komponent. Väggen som matchar kommer att rendera den kopplade komponenten.
Till exempel, för att skapa en grundläggande routerstruktur, skulle vi ha kod som ser ut som följer:
I det här fallet skapar vi en uppsättning vägar, där varje väg mappas till en specifik komponent. Vi använder även ett layoutkomponent (RootLayout) som fungerar som en gemensam wrapper för alla sidor, medan Outlet-komponenten från React Router gör det möjligt för oss att dynamiskt rendera de olika komponenterna beroende på den aktuella vägen.
En annan viktig aspekt av en sådan router är att hantera felaktiga vägar, där en användare kan navigera till en väg som inte existerar. För detta ändamål kan vi skapa en NotFound-komponent som hanterar fall där användaren försöker gå till en sida som inte är definierad. I så fall kan vi skapa en catch-all route genom att använda * som mönster för att fånga upp alla odefinierade vägar.
Genom att lägga till en catch-all route (med *) säkerställer vi att användare som försöker navigera till en ogiltig URL kommer att mötas av en användarvänlig felmeddelandesida, som till exempel en enkel "Page Not Found"-komponent.
Vidare, när vi arbetar med React Router, är det viktigt att förstå hur komponenter kan "nestas". Detta innebär att vi kan skapa en layoutkomponent som innehåller ytterligare "undersidor" eller sektioner, som också kan renderas i ett specifikt område på sidan. För att detta ska fungera korrekt använder vi Outlet i layoutkomponenten, vilket gör det möjligt att rendera specifika komponenter för de olika vägarna som definieras i routerkonfigurationen.
En typisk RootLayout-komponent som använder Outlet ser ut så här:
Med denna struktur renderas huvudlayouten hela tiden, men olika undersidor visas beroende på vilken väg användaren navigerar till. Detta gör att vi kan bygga en applikation med dynamiskt innehåll och navigering utan att behöva ladda om sidan varje gång användaren byter ruta.
En annan viktig aspekt att tänka på när vi jobbar med React Router är användningen av "loaders". Dessa funktioner gör det möjligt att hämta data innan komponenten laddas, vilket gör det möjligt att förbereda allt innehåll innan användaren ser sidan. Detta kan vara särskilt användbart om vi behöver hämta data från en extern API eller backend innan sidan visas.
För att använda loaders i React Router kan vi definiera en loaderfunktion som hämtar data och returnerar den innan sidan laddas. Detta kan göras genom att använda useLoaderData-hooken, som ger oss tillgång till datan när komponenten har laddats.
Till exempel, för att hämta data för en lista av bilar, kan vi skapa en loader som ser ut så här:
Denna loader kan kopplas till en specifik route, och när vägen laddas kommer den att hämta data från backend innan sidan visas. Loaderfunktionen gör det möjligt att förbereda och optimera sidladdning, vilket gör användarupplevelsen mer effektiv och snabb.
För att sammanfatta: att använda React Router för att skapa en navigerbar applikation kräver en förståelse för hur man definierar vägar och komponenter, hur man hanterar felaktiga vägar med en NotFound-sida, och hur man kan förbättra prestanda med hjälp av funktioner som loaders. När alla dessa element sätts ihop, skapar man en applikation där innehållet kan uppdateras och navigeras utan att behöva ladda om hela sidan, vilket gör användarupplevelsen mer smidig och snabb.
Hur man bygger en grundläggande appstruktur med Next.js: Routing och layout
När du arbetar med Next.js för att bygga en webbapplikation, är en viktig aspekt att förstå hur man skapar och hanterar routing och layout. Next.js introducerar ett koncept som kallas "App Router", vilket ger utvecklare möjlighet att bygga både statiska och dynamiska rutter för att hantera användargränssnittets struktur och navigering. I denna sektion kommer vi att utforska hur man skapar grundläggande sidor och rutter, samt hanterar layout och komponenter för en effektiv applikation.
Först skapar du den grundläggande sidstrukturen för din applikation. En hemsida, en sida för att visa alla bilar, en individuell bilsida, en privat sida för att lägga till nya bilar (enbart för auktoriserade användare), och en inloggningssida. Den första filen som du skapar är page.js, som finns i roten av App-mappen. Detta kommer att mappa till URL:en / på webbplatsen. Därefter skapar du sidor för att visa alla bilar, individuella bilar, samt sidor för inloggning och privata sidor.
För att skapa en rutt som visar bilar, skapar du en ny mapp med namnet cars i /app-katalogen och lägger till en enkel page.js-fil där. Inuti denna fil kan du skapa en funktion som returnerar en lista över bilar:
Vidare skapar du en dynamisk rutt för att visa en specifik bil baserat på dess ID. För detta skapar du en ny mapp i /cars-mappen och döper den till [id]. Detta gör att routern känner igen att URL:en /cars/someID ska visas när ett specifikt ID begärs. Inuti [id]-mappen skapar du en page.js-fil och definierar en komponent som hanterar visningen av den specifika bilen:
Efter att ha skapat dessa sidor kan du testa dem genom att manuellt besöka URL:erna /, /cars, /private och /login. Detta är den grundläggande strukturen för att skapa en webbapplikation med Next.js:s App Router, där varje ruta är definierad av mapparnas och filernas placering.
När vi talar om routing är det också viktigt att förstå hur "layouts" fungerar i Next.js. Precis som i andra lösningar, som React Router och dess Slot-komponent, erbjuder Next.js en layoutkomponent som gör det möjligt att definiera gemensamma användargränssnitt för relaterade rutter. Layoutkomponenten är mycket kraftfull eftersom den gör det möjligt att skapa återanvändbara delar av användargränssnittet, vilket inte behöver renderas om vid varje sidladdning.
Till exempel, om du skapar en layout för en sida som visar alla bilar och en individuell bil, kan du definiera en layoutkomponent i /app/cars/layout.js:
Denna layout kommer att tillämpas på både /cars och /cars/[id], men inte på andra sidor i applikationen. Placeringen av layoutfilen i filstrukturen definierar var och när layouten kommer att laddas. Detta ger utvecklaren möjlighet att skapa en flexibel och effektiv struktur för appens användargränssnitt.
Vidare erbjuder Next.js några ytterligare funktioner som gör routing ännu mer flexibel. "Catch-all"-segment, definierade med ellipser ([...]), kan matcha fler path-parametrar och tillåter dig att skapa ännu mer dynamiska och komplexa rutter. Dessutom gör route groups det möjligt att hålla vissa delar av applikationen isolerade från URL:en men ändå bibehålla layoutfunktionalitet.
När du väl har byggt de nödvändiga sidorna och lärt dig om de viktigaste funktionerna i App Router, är nästa steg att börja använda komponenter i din applikation. En central aspekt av Next.js är skillnaden mellan serverkomponenter och klientkomponenter. Serverkomponenter renderas på servern och kan cachas, vilket gör dem lämpliga för dataläsning och hantering av känslig information som API-nycklar och access tokens. Klientkomponenter å andra sidan används för interaktivitet på klienten, såsom React Hooks och användarinteraktioner i webbläsaren.
För att skapa en navigeringskomponent i Next.js kan du implementera en enkel NavBar.js i /src/components/:
Denna komponent använder Next.js Link-komponent för att länka mellan sidorna och ger användaren en snabb navigering mellan de definierade rutter.
Vidare är det viktigt att förstå skillnaderna mellan server- och klientkomponenter när du bygger en applikation i Next.js. Serverkomponenter gör det möjligt att dra nytta av server-side rendering (SSR) och server-side datahämtning, medan klientkomponenter ger flexibilitet för att skapa dynamiska och interaktiva användargränssnitt i webbläsaren.

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский