I dagens webbutveckling är användning av tredje parts tjänster en självklarhet för att bygga kraftfulla och skalbara applikationer. FastAPI, som är en snabb och modern webbramverk för Python, underlättar integrationen av dessa tjänster genom sin flexibilitet och användarvänliga syntax. I denna sektion kommer vi att gå igenom ett exempel där vi integrerar OpenAI:s API för att skapa produktbeskrivningar och skicka dem via e-post. Det kommer att ge oss insikt i hur man implementerar bakgrundsprocesser, interagerar med externa tjänster och hanterar autentisering och datauppdatering i en FastAPI-applikation.

Först och främst, låt oss titta på hur en användare loggar in och autentiseras i systemet. Om en användare loggar in korrekt, bekräftar vi lösenordet och genererar en autentiseringstoken, vilket gör att användaren kan interagera med applikationen på ett säkert sätt. Här använder vi en bakgrundsuppgift som körs i parallell med själva login-processen för att skicka en logginformation som kan vara användbar för analys eller andra syften.

python
if user and auth_handler.verify_password(
loginUser.password, user.password ): token = auth_handler.encode_token( str(user.id), user.username ) background_tasks.add_task( delayed_task, username=user.username ) response = JSONResponse( content={ "token": token, "username": user.username } ) return response else: raise HTTPException( status_code=401, detail="Invalid username or password" )

I koden ovan kan vi se hur vi skapar en token och lägger till en bakgrundsuppgift med hjälp av background_tasks.add_task. Bakgrundsuppgifter är användbara när vi vill att en viss uppgift ska köras oberoende av huvudflödet, vilket tillåter oss att fortsätta med användarinteraktionen utan att blockera servern.

För att effektivt använda externa tjänster som OpenAI krävs det att vi först har en giltig API-nyckel och rätt inställningar i applikationen. Genom att importera nödvändiga bibliotek och konfigurera en OpenAI-klient kan vi börja kommunicera med API:t. I det här fallet syftar vi till att skapa en produktbeskrivning för en bil, baserat på parametrar som märke, modell och år.

python
import json from openai import OpenAI from config import BaseConfig from models import Car settings = BaseConfig() client = OpenAI(api_key=settings.OPENAI_API_KEY)

För att göra det enklare att generera prompts till OpenAI använder vi en funktion som bygger en textsträng baserat på bilens information. Denna textsträng används för att skapa en beskrivning av bilen samt lista för- och nackdelar.

python
def generate_prompt(brand: str, model: str, year: int) -> str:
return f""" You are a helpful car sales assistant. Describe the {brand} {model} from {year} in a playful manner. Also, provide five pros and five cons of the model, but formulate the cons in a not overly negative way. You will respond with a JSON format consisting of the following: a brief description of the {brand} {model}, playful and positive, but not over the top. This will be called *description*. an array of 5 brief *pros* of the car model, short and concise, maximum 12 words, slightly positive and playful. an array of 5 brief *cons* drawbacks of the car model, short and concise, maximum 12 words, not too negative, but in a slightly negative tone. """

Genom att anropa OpenAI:s API får vi tillbaka en beskrivning, fördelar och nackdelar i JSON-format. Dessa data används sedan för att uppdatera bilens information i vår databas via Beanie och MongoDB.

python
async def create_description(brand, make, year, picture_url):
prompt = generate_prompt(brand, make, year) try: response = client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": prompt}], max_tokens=500, temperature=0.2, ) content = response.choices[0].message.content car_info = json.loads(content) await Car.find( Car.brand == brand, Car.make == make, Car.year == year ).set({ "description": car_info["description"], "pros": car_info["pros"], "cons": car_info["cons"], }) except Exception as e: print(e)

I denna funktion ser vi hur vi anropar OpenAI:s chat.completions.create metod, där vi skickar prompten som vi tidigare har skapat och får tillbaka en genererad textbeskrivning. Denna beskrivning lagras sedan i databasen.

För att få denna bakgrundsuppgift att köras i rätt sammanhang, kan vi integrera den i vårt API:

python
@router.post( "/", response_description="Add new car with picture", response_model=Car, status_code=status.HTTP_201_CREATED, ) async def add_car_with_picture( background_tasks: BackgroundTasks, brand: str = Form("brand"), make: str = Form("make"), year: int = Form("year"), cm3: int = Form("cm3"), km: int = Form("km"), price: int = Form("price"), picture: UploadFile = File("picture"), user_data=Depends(auth_handler.auth_wrapper), ): background_tasks.add_task( create_description, brand, make, year, picture_url ) # Resten av koden för att lägga till bilen

I detta exempel läggs bakgrundsuppgiften create_description till i POST-endpointen för att skapa en ny bil med bild. Bakgrundsuppgiften hanteras asynkront, vilket betyder att användaren inte behöver vänta på att bilbeskrivningen ska genereras för att slutföra sin förfrågan.

Detta tillvägagångssätt gör att vi kan använda externa API:er som OpenAI effektivt och utan att blockera huvudflödet i applikationen. Det är en bra metod för att förbättra användarupplevelsen och samtidigt automatisera och optimera uppgifter som annars skulle ta för lång tid.

Det är också viktigt att notera att varje bakgrundsuppgift är beroende av att vi har ordentliga felhanteringsmekanismer, både för att kunna hantera eventuella problem som kan uppstå när vi kommunicerar med externa tjänster och för att säkerställa att våra användare inte påverkas negativt av systemfel.

Hur ska man modellera data effektivt i MongoDB?

MongoDB är ett kraftfullt verktyg för att hantera stora mängder data i moderna webbaserade applikationer, och dess flexibilitet gör den till en populär lösning för utvecklare som söker alternativ till traditionella relationsdatabaser. Dock kan det vara utmanande att förstå hur man bäst organiserar och strukturerar data i MongoDB för att dra nytta av dess unika fördelar. Denna del kommer att belysa några viktiga överväganden och bästa praxis som bör beaktas när man utformar datamodeller i MongoDB.

En av de första sakerna som bör förstås är att en bra datamodell bör reflektera hur applikationen kommer att använda datan och hur flödet av data ser ut. Detta innebär att när man planerar sin databasstruktur, måste man börja med att tänka på de specifika frågorna som kommer att ställas till databasen. En väldesignad datamodell gör det enkelt att hämta data effektivt och undviker onödiga komplexiteter som kan uppstå om man inte tar hänsyn till användningsmönstren från början.

När det gäller MongoDB och datamodellering är en grundläggande fråga om man ska använda embedding eller referencing för att definiera relationer mellan dokument. I MongoDB skiljer sig dessa tekniker från traditionella SQL-databaser där man ofta använder JOINs. MongoDB rekommenderar att objekt som används tillsammans bör kombineras i samma dokument. Det finns ett ofta citerat uttryck: "Data som används tillsammans bör förbli tillsammans". Om du vet att vissa objekt alltid kommer att användas samtidigt, bör du överväga att "bädda in" dessa i samma dokument. Detta minskar behovet av att göra dyra nätverksanrop eller att sammanfoga data från flera källor.

När det gäller att dela upp objekt i olika dokument är det viktigt att tänka på att undvika att använda JOINs om det inte är absolut nödvändigt. Fastän MongoDB stöder en form av JOIN-operation genom sitt aggregationsramverk, bör det användas sparsamt eftersom det kan leda till prestandaförluster om det inte hanteras korrekt.

En annan faktor att överväga när man skapar datamodeller är användningsfrekvensen för olika typer av data. Data som används frekvent bör vara lättillgänglig och optimerad för snabb åtkomst. Därför måste du alltid fråga dig själv: "Vilka data kommer att användas mest och hur kan jag strukturera dem för att undvika flaskhalsar i prestanda?" Här är det viktigt att strukturera scheman baserat på hur ofta datan används snarare än att skapa en alltför komplex modell från början. Datan bör vara lätt att hämta för de mest frekventa användningsfallen.

I MongoDB är relationerna mellan dokument i princip antingen en-till-en, en-till-många eller många-till-många. För de första två relationstyperna rekommenderas oftast embedding. För relationer där det finns en stor mängd objekt på den "många" sidan, kan det vara bättre att använda referencing. MongoDB-dokumentationen rekommenderar att använda referencing i många-till-många-fall och i de situationer där objekt på den många sidan kan bli mycket stora och orsaka prestandaproblem om de bäddas in.

För att förstå detta bättre kan vi tänka på en verklig tillämpning. Låt oss säga att du arbetar med en användardatabas för en e-handelsapplikation. En användare kan ha många beställningar. Om varje beställning innehåller stora mängder data, är det bäst att referera till beställningarna från användardokumentet istället för att bädda in alla beställningar i samma dokument som användaren. Detta minskar storleken på dokumentet och gör det mer hanterbart.

För de som är nybörjare i MongoDB och datahantering, kan det vara användbart att experimentera med olika datamodeller genom att skapa små prototyper. Verktyg som PyMongo och Motor är bra för att komma igång med MongoDB i Python, och genom att använda dessa kan du snabbt justera och testa olika modeller för att hitta den bästa lösningen för ditt specifika användningsfall. Dessutom finns det andra Python-bibliotek som kan underlätta utvecklingen, som Beanie, som gör det lättare att arbeta asynkront med MongoDB.

Det är också viktigt att förstå hur MongoDB interagerar med andra teknologier. När du arbetar med FastAPI, en modern webbramverk för Python, är det viktigt att tänka på hur databasanslutningarna hanteras. FastAPI och MongoDB kan integreras på ett smidigt sätt, men det är viktigt att följa bästa praxis för att se till att din applikation är både snabb och säker.

Strukturering av applikationer i FastAPI och Python är också en nyckelfaktor för att skapa skalbara och hållbara applikationer. Det är lätt att skapa en applikation i ett enda Python-skript, men detta leder ofta till svårigheter att underhålla och vidareutveckla koden. Istället bör du organisera din applikation genom att dela upp den i olika delar, som till exempel routers och modeller, för att skapa en mer modulär och hanterbar struktur. Detta kommer att göra det enklare att utveckla och testa din applikation över tid.

En annan viktig aspekt är testning. För att säkerställa att din MongoDB-integration fungerar som den ska, bör du skriva enhetstester för alla API-endpoints. FastAPI underlättar denna process genom sin integration med Pydantic och genom att generera automatisk dokumentation för API:et. Detta gör det lättare att testa och felsöka din kod, och minskar risken för att oförutsedda problem uppstår i produktion.

För att verkligen få ut det mesta av MongoDB och FastAPI är det också viktigt att ständigt uppdatera dina kunskaper och hålla dig ajour med nya teknologier och bästa praxis. Att förstå när och hur man ska använda olika mönster, som embedding eller referencing, och att känna till hur man strukturerar sina applikationer effektivt, kommer att göra dig till en bättre utvecklare och hjälpa dig skapa robusta och högpresterande applikationer.