FastAPI-യിൽ അസynchronous ഡാറ്റാബേസ് സംയോജനം എങ്ങനെ ചെയ്യാമെന്ന് പഠിച്ച് ഉയർന്ന പ്രകടനം കാഴ്ചവെക്കുന്ന വെബ് ആപ്ലിക്കേഷനുകൾ നേടുക. SQLAlchemy, Databases ലൈബ്രറി ഉദാഹരണങ്ങളോടുകൂടിയുള്ള സമഗ്രമായ ഒരു ഗൈഡ്.
FastAPI ഡാറ്റാബേസ് സംയോജനം: അസynchronous ഡാറ്റാബേസ് പ്രവർത്തനങ്ങളിലേക്ക് ഒരു ആഴത്തിലുള്ള യാത്ര
ആധുനിക വെബ് ഡെവലപ്മെൻ്റിൻ്റെ ലോകത്ത്, പ്രകടനം ഒരു സവിശേഷത മാത്രമല്ല; ഇതൊരു അടിസ്ഥാന ആവശ്യകതയുമാണ്. ഉപയോക്താക്കൾ വേഗതയേറിയതും പ്രതികരിക്കുന്നതുമായ ആപ്ലിക്കേഷനുകൾ പ്രതീക്ഷിക്കുന്നു, കൂടാതെ ഈ പ്രതീക്ഷകൾ നിറവേറ്റുന്നതിന് ഡെവലപ്പർമാർ നിരന്തരം ടൂളുകളും ടെക്നിക്കുകളും തേടുന്നു. അതിശയകരമായ വേഗതയ്ക്ക് പേരുകേട്ട, Python ഇക്കോസിസ്റ്റത്തിൽ FastAPI ഒരു ശക്തിയായി മാറിയിട്ടുണ്ട്, പ്രധാനമായും ഇതിൻ്റെ അസynchronous സ്വഭാവം കാരണമാണ് ഇത് സാധ്യമാകുന്നത്. എന്നിരുന്നാലും, വേഗതയേറിയ ഒരു ഫ്രെയിംവർക്ക് എന്നത് ഒരു ഭാഗം മാത്രമാണ്. നിങ്ങളുടെ ആപ്ലിക്കേഷൻ ഒരു മന്ദഗതിയിലുള്ള ഡാറ്റാബേസിനായി കാത്തിരുന്ന് കൂടുതൽ സമയം ചെലവഴിക്കുകയാണെങ്കിൽ, നിങ്ങൾ ട്രാഫിക് ബ്ലോക്കിൽ കുടുങ്ങിയ ഒരു ഉയർന്ന പ്രകടനമുള്ള എഞ്ചിനാണ് ഉണ്ടാക്കിയിരിക്കുന്നത്.
ഇവിടെയാണ് അസynchronous ഡാറ്റാബേസ് പ്രവർത്തനങ്ങൾ നിർണായകമാകുന്നത്. നിങ്ങളുടെ FastAPI ആപ്ലിക്കേഷനെ മുഴുവൻ പ്രക്രിയയും തടസ്സപ്പെടുത്താതെ ഡാറ്റാബേസ് ചോദ്യങ്ങൾ കൈകാര്യം ചെയ്യാൻ അനുവദിക്കുന്നതിലൂടെ, നിങ്ങൾക്ക് യഥാർത്ഥ കോൺകറൻസി അൺലോക്ക് ചെയ്യാനും വേഗതയേറിയതും എന്നാൽ വളരെ സ്കേലബിളുമായ ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കാനും കഴിയും. FastAPI-യുമായി അസynchronous ഡാറ്റാബേസുകൾ എങ്ങനെ സംയോജിപ്പിക്കാമെന്ന് ഈ സമഗ്രമായ ഗൈഡ് നിങ്ങളെ പഠിപ്പിക്കും, അതുവഴി ആഗോള പ്രേക്ഷകർക്കായി ഉയർന്ന പ്രകടനം കാഴ്ചവെക്കുന്ന സേവനങ്ങൾ നിർമ്മിക്കാൻ നിങ്ങളെ പ്രാപ്തരാക്കുന്നു.
കോർ ആശയം: എന്തുകൊണ്ടാണ് അസynchronous I/O പ്രാധാന്യമർഹിക്കുന്നത്
കോഡിലേക്ക് കടക്കുന്നതിന് മുമ്പ്, അസിങ്ക് പ്രവർത്തനങ്ങൾ പരിഹരിക്കുന്ന അടിസ്ഥാന പ്രശ്നം മനസ്സിലാക്കേണ്ടത് അത്യാവശ്യമാണ്: I/O-ബൗണ്ട് കാത്തിരിപ്പ്.
ഒരു അടുക്കളയിലെ അതി വിദഗ്ദ്ധനായ ഒരു ഷെഫിനെക്കുറിച്ച് ചിന്തിക്കുക. ഒരു synchronous (അഥവാ ബ്ലോക്കിംഗ്) മാതൃകയിൽ, ഈ ഷെഫ് ഒരു സമയം ഒരു ടാസ്ക് മാത്രമേ ചെയ്യുകയുള്ളൂ. അവർ വെള്ളം തിളപ്പിക്കാൻ അടുപ്പിൽ വെക്കുകയും, അത് തിളക്കുന്നതുവരെ അവിടെ കാത്തിരിക്കുകയും ചെയ്യും. വെള്ളം തിളച്ചതിന് ശേഷം മാത്രമേ പച്ചക്കറികൾ അരിയാൻ തുടങ്ങുകയുള്ളൂ. ഇത് വളരെ കാര്യക്ഷമമല്ലാത്ത ഒന്നാണ്. കാത്തിരിപ്പ് കാലയളവിൽ (I/O പ്രവർത്തനം) ഷെഫിൻ്റെ സമയം (CPU) പാഴായിപ്പോകുന്നു.
ഇനി, ഒരു asynchronous (നോൺ-ബ്ലോക്കിംഗ്) മോഡൽ പരിഗണിക്കുക. ഷെഫ് വെള്ളം തിളപ്പിക്കാൻ വെക്കുകയും കാത്തിരിക്കുന്നതിന് പകരം, ഉടൻ തന്നെ പച്ചക്കറികൾ അരിയാൻ തുടങ്ങുകയും ചെയ്യുന്നു. അവർക്ക് അടുപ്പിൽ ഒരു ട്രേ വെക്കാനും കഴിയും. pombal, അവർക്ക് ടാസ്ക്കുകൾക്കിടയിൽ മാറിയും, pombal വേഗത കുറഞ്ഞ പ്രവർത്തനങ്ങൾ (വെള്ളം തിളപ്പിക്കുകയോ ബേക്ക് ചെയ്യുകയോ ചെയ്യുന്നത് പോലെ) പൂർത്തിയാകുന്നതുവരെ കാത്തിരിക്കാനും കഴിയും. ഒരു ടാസ്ക് പൂർത്തിയാകുമ്പോൾ (വെള്ളം തിളയ്ക്കുമ്പോൾ), ഷെഫിനെ അറിയിക്കുകയും pombal ആ വിഭവത്തിൻ്റെ അടുത്ത ഘട്ടത്തിലേക്ക് പോകുകയും ചെയ്യും.
ഒരു വെബ് ആപ്ലിക്കേഷനിൽ, ഡാറ്റാബേസ് ചോദ്യങ്ങൾ, API കോളുകൾ, ഫയലുകൾ വായിക്കുക എന്നിവയെല്ലാം വെള്ളം തിളക്കുന്നതിനായി കാത്തിരിക്കുന്നതിന് തുല്യമാണ്. ഒരു പരമ്പരാഗത synchronous ആപ്ലിക്കേഷൻ ഒരു അഭ്യർത്ഥന കൈകാര്യം ചെയ്യും, ഡാറ്റാബേസിലേക്ക് ഒരു ചോദ്യം അയയ്ക്കും, തുടർന്ന് ഡാറ്റാബേസ് പ്രതികരിക്കുന്നതുവരെ മറ്റ് ഇൻകമിംഗ് അഭ്യർത്ഥനകൾ തടയുകയും ചെയ്യും. Python-ൻ്റെ `asyncio`, FastAPI പോലുള്ള ഫ്രെയിംവർക്കുകൾ എന്നിവ ഉപയോഗിച്ച് പ്രവർത്തിക്കുന്ന ഒരു asynchronous ആപ്ലിക്കേഷന്, I/O-വിനായി കാത്തിരിക്കുമ്പോൾ അവയ്ക്കിടയിൽ കാര്യക്ഷമമായി മാറിയ ശേഷം ആയിരക്കണക്കിന് സമകാലിക കണക്ഷനുകൾ കൈകാര്യം ചെയ്യാൻ കഴിയും.
അസിങ്ക് ഡാറ്റാബേസ് പ്രവർത്തനങ്ങളുടെ പ്രധാന നേട്ടങ്ങൾ:
- വർദ്ധിച്ച കോൺകറൻസി: ഒരേ ഹാർഡ്വെയർ വിഭവങ്ങൾ ഉപയോഗിച്ച് ഒരേസമയം ധാരാളം ഉപയോക്താക്കളെ കൈകാര്യം ചെയ്യുക.
- മെച്ചപ്പെട്ട ത്രൂപുട്ട്: ഡാറ്റാബേസിനായി കാത്തിരുന്ന് ആപ്ലിക്കേഷൻ കുടുങ്ങിക്കിടക്കാത്തതിനാൽ, ഒരു സെക്കൻഡിൽ കൂടുതൽ അഭ്യർത്ഥനകൾ പ്രോസസ്സ് ചെയ്യുക.
- മെച്ചപ്പെടുത്തിയ ഉപയോക്തൃ അനുഭവം: വേഗത്തിലുള്ള പ്രതികരണ സമയം, ഉപയോക്താവിന് കൂടുതൽ പ്രതികരിക്കുന്നതും സംതൃപ്തികരവുമായ അനുഭവം നൽകുന്നു.
- വിഭവ കാര്യക്ഷമത: CPU, മെമ്മറി എന്നിവയുടെ മികച്ച ഉപയോഗം, ഇത് കുറഞ്ഞ അടിസ്ഥാന സൗകര്യങ്ങളുടെ ചിലവിലേക്ക് നയിച്ചേക്കാം.
നിങ്ങളുടെ അസynchronous വികസന അന്തരീക്ഷം സജ്ജമാക്കുന്നു
ആരംഭിക്കുന്നതിന്, നിങ്ങൾക്ക് കുറച്ച് പ്രധാന ഘടകങ്ങൾ ആവശ്യമാണ്. ഈ ഉദാഹരണങ്ങൾക്കായി ഞങ്ങൾ PostgreSQL-നെ ഡാറ്റാബേസായി ഉപയോഗിക്കും, കാരണം ഇതിന് അസynchronous ഡ്രൈവർമാർക്ക് മികച്ച പിന്തുണയുണ്ട്. എന്നിരുന്നാലും, async ഡ്രൈവർമാരുള്ള MySQL, SQLite പോലുള്ള മറ്റ് ഡാറ്റാബേസുകൾക്കും ഈ തത്വങ്ങൾ ബാധകമാണ്.
1. കോർ ഫ്രെയിംവർക്കും സെർവറും
ആദ്യം, FastAPI-യും Uvicorn പോലുള്ള ഒരു ASGI സെർവറും ഇൻസ്റ്റാൾ ചെയ്യുക.
pip install fastapi uvicorn[standard]
2. നിങ്ങളുടെ Async ഡാറ്റാബേസ് ടൂൾകിറ്റ് തിരഞ്ഞെടുക്കുന്നു
നിങ്ങളുടെ ഡാറ്റാബേസുമായി asynchronously സംസാരിക്കാൻ നിങ്ങൾക്ക് രണ്ട് പ്രധാന ഘടകങ്ങൾ ആവശ്യമാണ്:
- ഒരു Async ഡാറ്റാബേസ് ഡ്രൈവർ: async പ്രോട്ടോക്കോൾ ഉപയോഗിച്ച് നെറ്റ്വർക്കിലൂടെ ഡാറ്റാബേസുമായി ആശയവിനിമയം നടത്തുന്ന, താഴ്ന്ന നിലയിലുള്ള ലൈബ്രറിയാണ് ഇത്. PostgreSQL-ൽ,
asyncpgസാധാരണയായി ഉപയോഗിക്കുന്ന ഒന്നാണ്, കൂടാതെ അതിൻ്റെ അവിശ്വസനീയമായ പ്രകടനത്തിന് ഇത് അറിയപ്പെടുന്നു. - ഒരു Async ചോദ്യം ബിൽഡറോ ORM-ഓ: നിങ്ങളുടെ ചോദ്യങ്ങൾ എഴുതുന്നതിന് ഉയർന്ന നിലവാരമുള്ളതും, കൂടുതൽ പൈത്തണിക്തുമായ ഒരു വഴി ഇത് നൽകുന്നു. ഞങ്ങൾ രണ്ട് ജനപ്രിയ ഓപ്ഷനുകൾ പര്യവേക്ഷണം ചെയ്യും:
databases: റോ SQL എക്സിക്യൂഷനായി ഒരു ലളിതമായ API നൽകുന്ന, ലളിതവും ഭാരം കുറഞ്ഞതുമായ ഒരു async ചോദ്യം ബിൽഡർ.SQLAlchemy 2.0+: ശക്തവും ഫീച്ചർ-സമ്പന്നവുമായ SQLAlchemy ORM-ൻ്റെ ഏറ്റവും പുതിയ പതിപ്പുകളിൽ `asyncio`-യ്ക്കുള്ള നേറ്റീവ്, ഒന്നാം ക്ലാസ് പിന്തുണ ഉൾപ്പെടുന്നു. സങ്കീർണ്ണമായ ആപ്ലിക്കേഷനുകൾക്കായി ഇത് പലപ്പോഴും തിരഞ്ഞെടുക്കാറുണ്ട്.
3. ഇൻസ്റ്റാളേഷൻ
ആവശ്യമുള്ള ലൈബ്രറികൾ ഇൻസ്റ്റാൾ ചെയ്യാം. നിങ്ങൾക്ക് ടൂൾകിറ്റുകളിലൊന്ന് തിരഞ്ഞെടുക്കാം അല്ലെങ്കിൽ പരീക്ഷിക്കുന്നതിനായി രണ്ടും ഇൻസ്റ്റാൾ ചെയ്യാം.
SQLAlchemy, `databases` എന്നിവയുള്ള PostgreSQL-നായി:
# Driver for PostgreSQL
pip install asyncpg
# For the SQLAlchemy 2.0+ approach
pip install sqlalchemy
# For the 'databases' library approach
pip install databases[postgresql]
ഞങ്ങളുടെ അന്തരീക്ഷം തയ്യാറായ ശേഷം, FastAPI ആപ്ലിക്കേഷനിലേക്ക് ഈ ടൂളുകൾ എങ്ങനെ സംയോജിപ്പിക്കാമെന്ന് നമുക്ക് പര്യവേക്ഷണം ചെയ്യാം.
തന്ത്രം 1: `databases` ലൈബ്രറിയുടെ ലളിതമായ ഉപയോഗം
databases ലൈബ്രറി ഒരു മികച്ച തുടക്കമാണ്. ഇത് ലളിതമാക്കാൻ രൂപകൽപ്പന ചെയ്തിട്ടുള്ളതാണ് കൂടാതെ അടിസ്ഥാനപരമായ async ഡ്രൈവർമാരിൽ നേരിയ ഒരു റാപ്പർ നൽകുന്നു, പൂർണ്ണമായ ഒരു ORM-ൻ്റെ സങ്കീർണ്ണതകളില്ലാതെ റോ SQL നടപ്പിലാക്കാനുള്ള അധികാരം ഇത് നിങ്ങൾക്ക് നൽകുന്നു.
ഘട്ടം 1: ഡാറ്റാബേസ് കണക്ഷനും ലൈഫ് സൈക്കിൾ മാനേജ്മെൻ്റും
ഒരു യഥാർത്ഥ ആപ്ലിക്കേഷനിൽ, എല്ലാ അഭ്യർത്ഥനകളിലും നിങ്ങൾ ഡാറ്റാബേസിലേക്ക് കണക്ട് ചെയ്യാനും വിച്ഛേദിക്കാനും ആഗ്രഹിക്കുന്നില്ല. ഇത് കാര്യക്ഷമമല്ലാത്ത ഒന്നാണ്. പകരം, ആപ്ലിക്കേഷൻ ആരംഭിക്കുമ്പോൾ ഞങ്ങൾ ഒരു കണക്ഷൻ പൂൾ സ്ഥാപിക്കുകയും അത് ഷട്ട്ഡൗൺ ചെയ്യുമ്പോൾ അത് മര്യാദയായി close ചെയ്യുകയും ചെയ്യും. FastAPI-യുടെ ഇവൻ്റ് കൈകാര്യം ചെയ്യുന്നവർ (`@app.on_event("startup")` കൂടാതെ `@app.on_event("shutdown")`) ഇതിന് വളരെ അനുയോജ്യമാണ്.
main_databases.py എന്ന് പേരുള്ള ഒരു ഫയൽ ഉണ്ടാക്കുക:
import databases
import sqlalchemy
from fastapi import FastAPI
# --- Database Configuration ---
# Replace with your actual database URL
# Format for asyncpg: "postgresql+asyncpg://user:password@host/dbname"
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/testdb"
database = databases.Database(DATABASE_URL)
# SQLAlchemy model metadata (for table creation)
metadata = sqlalchemy.MetaData()
# Define a sample table
notes = sqlalchemy.Table(
"notes",
metadata,
sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
sqlalchemy.Column("title", sqlalchemy.String(100)),
sqlalchemy.Column("content", sqlalchemy.String(500)),
)
# Create an engine for table creation (this part is synchronous)
# The 'databases' library doesn't handle schema creation
engine = sqlalchemy.create_engine(DATABASE_URL.replace("+asyncpg", ""))
metadata.create_all(engine)
# --- FastAPI Application ---
app = FastAPI(title="FastAPI with Databases Library")
@app.on_event("startup")
async def startup():
print("Connecting to database...")
await database.connect()
print("Database connection established.")
@app.on_event("shutdown")
async def shutdown():
print("Disconnecting from database...")
await database.disconnect()
print("Database connection closed.")
# --- API Endpoints ---
@app.get("/")
def read_root():
return {"message": "Welcome to the Async Database API!"}
പ്രധാന പോയിൻ്റുകൾ:
postgresql+asyncpgസ്കീം ഉപയോഗിച്ച് ഞങ്ങൾDATABASE_URLനിർവചിക്കുന്നു.- ഒരു ഗ്ലോബൽ
databaseഒബ്ജക്റ്റ് സൃഷ്ടിക്കപ്പെടുന്നു. startupഇവൻ്റ് കൈകാര്യം ചെയ്യുന്നയാൾawait database.connect()വിളിക്കുന്നു, ഇത് കണക്ഷൻ പൂൾ ആരംഭിക്കുന്നു.shutdownഇവൻ്റ് കൈകാര്യം ചെയ്യുന്നയാൾ എല്ലാ കണക്ഷനുകളും നന്നായി close ചെയ്യുന്നതിന്await database.disconnect()വിളിക്കുന്നു.
ഘട്ടം 2: അസynchronous CRUD എൻഡ്പോയിൻ്റുകൾ നടപ്പിലാക്കുന്നു
ഇനി, Create, Read, Update, and Delete (CRUD) പ്രവർത്തനങ്ങൾ ചെയ്യുന്നതിന് എൻഡ്പോയിൻ്റുകൾ ചേർക്കാം. ഡാറ്റാ മൂല്യനിർണയത്തിനും സീരിയലൈസേഷനുമായി ഞങ്ങൾ Pydantic ഉപയോഗിക്കും.
നിങ്ങളുടെ main_databases.py ഫയലിലേക്ക് താഴെ പറയുന്നവ ചേർക്കുക:
from pydantic import BaseModel
from typing import List, Optional
# --- Pydantic Models for data validation ---
class NoteIn(BaseModel):
title: str
content: str
class Note(BaseModel):
id: int
title: str
content: str
# --- CRUD Endpoints ---
@app.post("/notes/", response_model=Note)
async def create_note(note: NoteIn):
"""Create a new note in the database."""
query = notes.insert().values(title=note.title, content=note.content)
last_record_id = await database.execute(query)
return {**note.dict(), "id": last_record_id}
@app.get("/notes/", response_model=List[Note])
async def read_all_notes():
"""Retrieve all notes from the database."""
query = notes.select()
return await database.fetch_all(query)
@app.get("/notes/{note_id}", response_model=Note)
async def read_note(note_id: int):
"""Retrieve a single note by its ID."""
query = notes.select().where(notes.c.id == note_id)
result = await database.fetch_one(query)
if result is None:
raise HTTPException(status_code=404, detail="Note not found")
return result
@app.put("/notes/{note_id}", response_model=Note)
async def update_note(note_id: int, note: NoteIn):
"""Update an existing note."""
query = (
notes.update()
.where(notes.c.id == note_id)
.values(title=note.title, content=note.content)
)
result = await database.execute(query)
if result == 0:
raise HTTPException(status_code=404, detail="Note not found")
return {**note.dict(), "id": note_id}
@app.delete("/notes/{note_id}")
async def delete_note(note_id: int):
"""Delete a note by its ID."""
query = notes.delete().where(notes.c.id == note_id)
result = await database.execute(query)
if result == 0:
raise HTTPException(status_code=404, detail="Note not found")
return {"message": "Note deleted successfully"}
Async കോളുകളുടെ വിശകലനം:
await database.execute(query): INSERT, UPDATE, DELETE പോലുള്ള വരികൾ തിരികെ നൽകാത്ത പ്രവർത്തനങ്ങൾക്കായി ഉപയോഗിക്കുന്നു. ഇത് ബാധിച്ച വരികളുടെ എണ്ണം അല്ലെങ്കിൽ പുതിയ റെക്കോർഡിൻ്റെ പ്രൈമറി കീ നൽകുന്നു.await database.fetch_all(query): ഒന്നിലധികം വരികൾ പ്രതീക്ഷിക്കുന്ന SELECT ചോദ്യങ്ങൾക്കായി ഉപയോഗിക്കുന്നു. ഇത് റെക്കോർഡുകളുടെ ഒരു ലിസ്റ്റ് നൽകുന്നു.await database.fetch_one(query): നിങ്ങൾ ഒന്നോ അതിലധികമോ വരികൾ പ്രതീക്ഷിക്കുന്ന SELECT ചോദ്യങ്ങൾക്കായി ഉപയോഗിക്കുന്നു. ഇത് ഒരൊറ്റ റെക്കോർഡ് അല്ലെങ്കിൽNoneനൽകുന്നു.
എല്ലാ ഡാറ്റാബേസ് ഇടപെടലുകളും await എന്നതിനൊപ്പം ചേർത്തിരിക്കുന്നത് ശ്രദ്ധിക്കുക. ഡാറ്റാബേസ് പ്രതികരിക്കുന്നതിനായി കാത്തിരിക്കുമ്പോൾ, മറ്റ് ടാസ്ക്കുകളിലേക്ക് മാറാൻ ഇവൻ്റ് ലൂപ്പിനെ അനുവദിക്കുന്ന മാജിക് ആണിത്, ഇത് ഉയർന്ന കോൺകറൻസി പ്രാപ്തമാക്കുന്നു.
തന്ത്രം 2: ആധുനിക ശക്തികേന്ദ്രം - SQLAlchemy 2.0+ Async ORM
ലളിതമായ കാര്യങ്ങൾക്കായി databases ലൈബ്രറി മികച്ചതാണെങ്കിലും, വലിയ തോതിലുള്ള ആപ്ലിക്കേഷനുകൾ ഒരു പൂർണ്ണ ഫീച്ചർ ചെയ്ത ഒബ്ജക്റ്റ്-റിലേഷണൽ മാപ്പർ (ORM) ഉപയോഗിക്കുന്നതിൽ നിന്ന് പ്രയോജനം നേടുന്നു. ഒരു ORM-ന് ഡാറ്റാബേസ് റെക്കോർഡുകൾ പൈത്തൺ ഒബ്ജക്റ്റുകളായി പ്രവർത്തിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു, ഇത് ഡെവലപ്പർമാരുടെ ഉൽപാദനക്ഷമതയും കോഡ് നിലനിർത്തലും വളരെയധികം മെച്ചപ്പെടുത്തും. Python ലോകത്തിലെ ഏറ്റവും ശക്തമായ ORM ആണ് SQLAlchemy, കൂടാതെ അതിൻ്റെ 2.0+ പതിപ്പുകൾ അത്യാധുനിക നേറ്റീവ് async ഇന്റർഫേസ് നൽകുന്നു.
ഘട്ടം 1: Async എഞ്ചിനും സെഷനും സജ്ജീകരിക്കുന്നു
SQLAlchemy-യുടെ async പ്രവർത്തനക്ഷമതയുടെ കാതൽ AsyncEngine, AsyncSession എന്നിവയിലാണ്. സജ്ജീകരണം synchronous പതിപ്പിൽ നിന്ന് അൽപ്പം വ്യത്യസ്തമാണ്.
മെച്ചപ്പെട്ട ഘടനയ്ക്കായി, ഞങ്ങൾ ഞങ്ങളുടെ കോഡിനെ കുറച്ച് ഫയലുകളായി ക്രമീകരിക്കും: database.py, models.py, schemas.py, കൂടാതെ main_sqlalchemy.py.
database.py:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/testdb"
# Create an async engine
engine = create_async_engine(DATABASE_URL, echo=True)
# Create a session factory
# expire_on_commit=False prevents attributes from being expired after commit
AsyncSessionLocal = sessionmaker(
bind=engine, class_=AsyncSession, expire_on_commit=False
)
models.py:
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Note(Base):
__tablename__ = "notes"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(100), index=True)
content = Column(String(500))
schemas.py (Pydantic മോഡലുകൾ):
from pydantic import BaseModel
class NoteBase(BaseModel):
title: str
content: str
class NoteCreate(NoteBase):
pass
class Note(NoteBase):
id: int
class Config:
orm_mode = True
Pydantic മോഡലിൻ്റെ കോൺഫിഗറേഷൻ ക്ലാസിലെ `orm_mode = True` എന്നത് ഒരു പ്രധാന ഭാഗമാണ്. ഇത് നിഘണ്ടുക്കളിൽ നിന്ന് മാത്രമല്ല, ORM മോഡൽ ആട്രിബ്യൂട്ടുകളിൽ നിന്നും ഡാറ്റ വായിക്കാൻ Pydantic-നോട് പറയുന്നു.
ഘട്ടം 2: ഡിപ്പൻഡൻസി ഇൻജക്ഷൻ ഉപയോഗിച്ച് സെഷനുകൾ കൈകാര്യം ചെയ്യുന്നു
FastAPI-യിൽ ഡാറ്റാബേസ് സെഷനുകൾ കൈകാര്യം ചെയ്യാനുള്ള ഏറ്റവും മികച്ച മാർഗ്ഗം ഡിപ്പൻഡൻസി ഇൻജക്ഷൻ വഴിയാണ്. ഒരു അഭ്യർത്ഥനയ്ക്കായി ഒരു ഡാറ്റാബേസ് സെഷൻ നൽകുകയും ഒരു പിശക് സംഭവിച്ചാലും അത് പിന്നീട് close ചെയ്യുന്നു എന്ന് ഉറപ്പാക്കുകയും ചെയ്യുന്ന ഒരു ഡിപ്പൻഡൻസി ഞങ്ങൾ സൃഷ്ടിക്കും.
ഇത് നിങ്ങളുടെ main_sqlalchemy.py-യിലേക്ക് ചേർക്കുക:
from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from . import models, schemas
from .database import engine, AsyncSessionLocal
app = FastAPI()
# --- Dependency for getting a DB session ---
async def get_db() -> AsyncSession:
async with AsyncSessionLocal() as session:
try:
yield session
finally:
await session.close()
# --- Database Initialization (for creating tables) ---
@app.on_event("startup")
async def startup_event():
print("Initializing database schema...")
async with engine.begin() as conn:
# await conn.run_sync(models.Base.metadata.drop_all)
await conn.run_sync(models.Base.metadata.create_all)
print("Database schema initialized.")
get_db ഡിപ്പൻഡൻസി ഈ പാറ്റേണിൻ്റെ ഒരു പ്രധാന ഭാഗമാണ്. ഇത് ഉപയോഗിക്കുന്ന ഒരു എൻഡ്പോയിൻ്റിലേക്കുള്ള ഓരോ അഭ്യർത്ഥനയ്ക്കും, ഇത് ചെയ്യും:
- ഒരു പുതിയ
AsyncSessionഉണ്ടാക്കുക. - എൻഡ്പോയിൻ്റ് ഫംഗ്ഷനിലേക്ക് സെഷൻ
yieldചെയ്യുക. - അഭ്യർത്ഥന വിജയിച്ചാലും ഇല്ലെങ്കിലും സെഷൻ close ചെയ്യുന്നു എന്ന് ഉറപ്പാക്കാൻ
finallyബ്ലോക്കിനുള്ളിലെ കോഡ് ഉപയോഗിക്കുന്നു.
ഘട്ടം 3: SQLAlchemy ORM ഉപയോഗിച്ച് Async CRUD നടപ്പിലാക്കുന്നു
ഇനി നമുക്ക് എൻഡ്പോയിൻ്റുകൾ എഴുതാം. റോ SQL സമീപനത്തേക്കാൾ ഇത് കൂടുതൽ വൃത്തിയും ഒബ്ജക്റ്റ് ഓറിയന്റഡുമായിരിക്കും.
ഈ എൻഡ്പോയിൻ്റുകൾ main_sqlalchemy.py-യിലേക്ക് ചേർക്കുക:
@app.post("/notes/", response_model=schemas.Note)
async def create_note(
note: schemas.NoteCreate, db: AsyncSession = Depends(get_db)
):
db_note = models.Note(title=note.title, content=note.content)
db.add(db_note)
await db.commit()
await db.refresh(db_note)
return db_note
@app.get("/notes/", response_model=list[schemas.Note])
async def read_all_notes(skip: int = 0, limit: int = 100, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(models.Note).offset(skip).limit(limit))
notes = result.scalars().all()
return notes
@app.get("/notes/{note_id}", response_model=schemas.Note)
async def read_note(note_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(models.Note).filter(models.Note.id == note_id))
db_note = result.scalar_one_or_none()
if db_note is None:
raise HTTPException(status_code=404, detail="Note not found")
return db_note
@app.put("/notes/{note_id}", response_model=schemas.Note)
async def update_note(
note_id: int, note: schemas.NoteCreate, db: AsyncSession = Depends(get_db)
):
result = await db.execute(select(models.Note).filter(models.Note.id == note_id))
db_note = result.scalar_one_or_none()
if db_note is None:
raise HTTPException(status_code=404, detail="Note not found")
db_note.title = note.title
db_note.content = note.content
await db.commit()
await db.refresh(db_note)
return db_note
@app.delete("/notes/{note_id}")
async def delete_note(note_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(models.Note).filter(models.Note.id == note_id))
db_note = result.scalar_one_or_none()
if db_note is None:
raise HTTPException(status_code=404, detail="Note not found")
await db.delete(db_note)
await db.commit()
return {"message": "Note deleted successfully"}
SQLAlchemy Async പാറ്റേണിൻ്റെ വിശകലനം:
db: AsyncSession = Depends(get_db): ഇത് ഞങ്ങളുടെ ഡാറ്റാബേസ് സെഷനെ എൻഡ്പോയിൻ്റിലേക്ക് നൽകുന്നു.await db.execute(...): ചോദ്യങ്ങൾ പ്രവർത്തിപ്പിക്കുന്നതിനുള്ള പ്രധാന രീതിയാണിത്.result.scalars().all()/result.scalar_one_or_none(): ചോദ്യ ഫലത്തിൽ നിന്ന് യഥാർത്ഥ ORM ഒബ്ജക്റ്റുകൾ വേർതിരിച്ചെടുക്കാൻ ഈ രീതികൾ ഉപയോഗിക്കുന്നു.db.add(obj): ഒരു ഒബ്ജക്റ്റിനെ ചേർക്കാൻ സ്റ്റേജ് ചെയ്യുന്നു.await db.commit(): ഇടപാട് ഡാറ്റാബേസിലേക്ക് asynchronously സമർപ്പിക്കുന്നു. ഇത് ഒരു നിർണായക `await` പോയിൻ്റാണ്.await db.refresh(obj): കമ്മിറ്റിന് ശേഷം ഡാറ്റാബേസിൽ നിന്നുള്ള ഏതെങ്കിലും പുതിയ ഡാറ്റ ഉപയോഗിച്ച് പൈത്തൺ ഒബ്ജക്റ്റിനെ refresh ചെയ്യുന്നു (ഓട്ടോ-ജനറേറ്റഡ് ID പോലെ).
പ്രകടന പരിഗണനകളും മികച്ച രീതികളും
`async`, `await` എന്നിവ ഉപയോഗിക്കുന്നത് ഒരു മികച്ച തുടക്കമാണ്, എന്നാൽ ശരിക്കും ശക്തവും ഉയർന്ന പ്രകടനവുമുള്ള ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിന്, ഈ മികച്ച രീതികൾ പരിഗണിക്കുക.
1. കണക്ഷൻ പൂളിംഗ് മനസ്സിലാക്കുക
databases, SQLAlchemy-യുടെ AsyncEngine എന്നിവ രണ്ടും പിന്നണിയിൽ ഒരു കണക്ഷൻ പൂൾ കൈകാര്യം ചെയ്യുന്നു. ഈ പൂൾ വ്യത്യസ്ത അഭ്യർത്ഥനകൾക്ക് വീണ്ടും ഉപയോഗിക്കാൻ കഴിയുന്ന തുറന്ന ഡാറ്റാബേസ് കണക്ഷനുകളുടെ ഒരു കൂട്ടം നിലനിർത്തുന്നു. ഇത് ഓരോ ചോദ്യത്തിനും ഒരു പുതിയ TCP കണക്ഷൻ സ്ഥാപിക്കുന്നതിൻ്റെയും, ഡാറ്റാബേസുമായി പ്രാമാണീകരിക്കുന്നതിൻ്റെയും വലിയ ഓവർഹെഡ് ഒഴിവാക്കുന്നു. നിങ്ങളുടെ പ്രത്യേക വർക്ക്ലോഡിനായി എഞ്ചിൻ കോൺഫിഗറേഷനിൽ പൂൾ വലുപ്പം (ഉദാഹരണത്തിന്, `pool_size`, `max_overflow`) നിങ്ങൾക്ക് ട്യൂൺ ചെയ്യാൻ കഴിയും.
2. Sync, Async ഡാറ്റാബേസ് കോളുകൾ ഒരിക്കലും മിക്സ് ചെയ്യരുത്
ഏറ്റവും പ്രധാനപ്പെട്ട നിയമം എന്തെന്നാൽ `async def` ഫംഗ്ഷനുള്ളിൽ ഒരു synchronous, ബ്ലോക്കിംഗ് I/O ഫംഗ്ഷൻ ഒരിക്കലും വിളിക്കരുത്. ഒരു സാധാരണ, synchronous ഡാറ്റാബേസ് കോൾ (ഉദാഹരണത്തിന്, `psycopg2` നേരിട്ട് ഉപയോഗിക്കുന്നത്) മുഴുവൻ ഇവൻ്റ് ലൂപ്പിനെയും തടയും, ഇത് നിങ്ങളുടെ ആപ്ലിക്കേഷനെ മരവിപ്പിക്കുകയും async-ൻ്റെ ലക്ഷ്യം പരാജയപ്പെടുത്തുകയും ചെയ്യുന്നു.
നിങ്ങൾ ഒരു synchronous കോഡ് പ്രവർത്തിപ്പിക്കേണ്ടതുണ്ടെങ്കിൽ (ഒരുപക്ഷേ ഒരു CPU-ബൗണ്ട് ലൈബ്രറി), ഇവൻ്റ് ലൂപ്പ് തടയുന്നത് ഒഴിവാക്കാൻ FastAPI-യുടെ `run_in_threadpool` ഉപയോഗിക്കുക:
from fastapi.concurrency import run_in_threadpool
@app.get("/run-sync-task/")
async def run_sync_task():
# 'some_blocking_io_function' is a regular sync function
result = await run_in_threadpool(some_blocking_io_function, arg1, arg2)
return {"result": result}
3. അസynchronous ഇടപാടുകൾ ഉപയോഗിക്കുക
ഒരു ഓപ്പറേഷനിൽ ഒന്നിലധികം ഡാറ്റാബേസ് മാറ്റങ്ങൾ ഉൾപ്പെടുമ്പോൾ, അവ ഒരുമിച്ച് വിജയിക്കണം അല്ലെങ്കിൽ പരാജയപ്പെടണം (ഒരു ആറ്റോമിക് ഓപ്പറേഷൻ), നിങ്ങൾ ഒരു ഇടപാട് ഉപയോഗിക്കണം. രണ്ട് ലൈബ്രറികളും ഒരു async context മാനേജർ വഴി ഇത് പിന്തുണയ്ക്കുന്നു.
`databases`- ഉപയോഗിച്ച്:
async def transfer_funds():
async with database.transaction():
await database.execute(query_for_debit)
await database.execute(query_for_credit)
SQLAlchemy ഉപയോഗിച്ച്:
async def transfer_funds(db: AsyncSession = Depends(get_db)):
async with db.begin(): # This starts a transaction
# Find accounts
account_from = ...
account_to = ...
# Update balances
account_from.balance -= 100
account_to.balance += 100
# The transaction is automatically committed on exiting the block
# or rolled back if an exception occurs.
4. നിങ്ങൾക്ക് ആവശ്യമുള്ളത് മാത്രം തിരഞ്ഞെടുക്കുക
നിങ്ങൾക്ക് കുറച്ച് കോളങ്ങൾ മാത്രമേ ആവശ്യമുള്ളൂ എങ്കിൽ `SELECT *` ഒഴിവാക്കുക. കുറഞ്ഞ ഡാറ്റ നെറ്റ്വർക്കിലൂടെ കൈമാറുന്നത് I/O കാത്തിരിപ്പ് സമയം കുറയ്ക്കുന്നു. SQLAlchemy ഉപയോഗിച്ച്, നിങ്ങൾക്ക് വീണ്ടെടുക്കേണ്ട കോളങ്ങൾ വ്യക്തമാക്കാൻ `options(load_only(model.col1, model.col2))` ഉപയോഗിക്കാം.
ഉപസംഹാരം: അസynchronous ഭാവി സ്വീകരിക്കുക
നിങ്ങളുടെ FastAPI ആപ്ലിക്കേഷനിലേക്ക് അസynchronous ഡാറ്റാബേസ് പ്രവർത്തനങ്ങൾ സംയോജിപ്പിക്കുന്നത് അതിൻ്റെ പൂർണ്ണമായ പ്രകടന സാധ്യതകൾ തുറക്കുന്നതിനുള്ള താക്കോലാണ്. ഡാറ്റാബേസിനായി കാത്തിരിക്കുമ്പോൾ നിങ്ങളുടെ ആപ്ലിക്കേഷൻ തടസ്സപ്പെടുന്നില്ലെന്ന് ഉറപ്പാക്കുന്നതിലൂടെ, വേഗതയേറിയതും, സ്കേലബിളും, കാര്യക്ഷമവുമായ സേവനങ്ങൾ നിങ്ങൾക്ക് നിർമ്മിക്കാൻ കഴിയും, കൂടാതെ ഒരു ആഗോള ഉപയോക്തൃ അടിത്തറയെ തടസ്സമില്ലാതെ സേവിക്കാൻ ഇത് പ്രാപ്തമാക്കുന്നു.
ഞങ്ങൾ രണ്ട് ശക്തമായ തന്ത്രങ്ങൾ പര്യവേക്ഷണം ചെയ്തു:
- `databases` ലൈബ്രറി SQL എഴുതാൻ താൽപ്പര്യപ്പെടുന്നവർക്കും ലളിതവും വേഗതയേറിയതുമായ async ഇന്റർഫേസ് ആവശ്യമുള്ളവർക്കും ലളിതവും, ഭാരം കുറഞ്ഞതുമായ ഒരു സമീപനം വാഗ്ദാനം ചെയ്യുന്നു.
- SQLAlchemy 2.0+ ഒരു നേറ്റീവ് async API-യോടുകൂടിയ പൂർണ്ണ ഫീച്ചർ ചെയ്ത, ശക്തമായ ORM നൽകുന്നു, ഇത് ഡെവലപ്പർ ഉൽപാദനക്ഷമതയും നിലനിർത്തലും പരമപ്രധാനമാകുമ്പോൾ സങ്കീർണ്ണമായ ആപ്ലിക്കേഷനുകൾക്ക് ഇത് ഏറ്റവും അനുയോജ്യമാക്കുന്നു.
അവയിലൊന്ന് തിരഞ്ഞെടുക്കുന്നത് നിങ്ങളുടെ പ്രോജക്റ്റിൻ്റെ ആവശ്യകതകളെ ആശ്രയിച്ചിരിക്കുന്നു, എന്നാൽ പ്രധാന തത്വം ഒന്നുതന്നെയാണ്: നോൺ-ബ്ലോക്കിംഗ് ആയി ചിന്തിക്കുക. ഈ രീതികളും മികച്ച രീതികളും സ്വീകരിക്കുന്നതിലൂടെ, നിങ്ങൾ കോഡ് എഴുതുക മാത്രമല്ല, ആധുനിക വെബിൻ്റെ ഉയർന്ന കോൺകറൻസി ആവശ്യകതകൾക്കായി സിസ്റ്റങ്ങൾ രൂപകൽപ്പന ചെയ്യുകയുമാണ്. ഇന്ന് നിങ്ങളുടെ അടുത്ത ഉയർന്ന പ്രകടനമുള്ള FastAPI ആപ്ലിക്കേഷൻ നിർമ്മിക്കാൻ ആരംഭിക്കുക, കൂടാതെ അസynchronous Python-ൻ്റെ ശക്തി നേരിട്ട് അനുഭവിക്കുക.