Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Prepare applications for Azure deployment by generating infrastructure code, Dockerfiles, and config files.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/services/app-service/templates/recipes/sql/source/python.md
1# SQL Database — Python — REFERENCE ONLY23## SQLAlchemy Setup45Add SQLAlchemy with Azure SQL and managed identity support to a FastAPI app.67### Requirements89Add to `requirements.txt`:1011```12sqlalchemy>=2.013pyodbc14azure-identity15fastapi16uvicorn17```1819### Database Configuration2021Create `database.py`:2223```python24import os25import struct26from sqlalchemy import create_engine, event27from sqlalchemy.orm import sessionmaker, DeclarativeBase28from azure.identity import ManagedIdentityCredential293031class Base(DeclarativeBase):32pass333435def create_db_engine():36"""Create SQLAlchemy engine using managed identity or connection string."""37conn_str = os.environ.get("AZURE_SQL_CONNECTION_STRING")38if conn_str:39# Local dev: AZURE_SQL_CONNECTION_STRING is a SQLAlchemy URL40# e.g. mssql+pyodbc://sa:password@localhost/myapp?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes41return create_engine(conn_str)4243# Azure: use managed identity token (refreshed per-connection so pool stays valid past 1 hour)44server = os.environ["AZURE_SQL_SERVER"]45database = os.environ["AZURE_SQL_DATABASE"]46client_id = os.environ.get("AZURE_CLIENT_ID")47credential = ManagedIdentityCredential(client_id=client_id) if client_id else ManagedIdentityCredential()4849odbc_conn = (50f"DRIVER={{ODBC Driver 18 for SQL Server}};"51f"SERVER={server};"52f"DATABASE={database};"53f"Encrypt=yes;TrustServerCertificate=no;"54)55engine = create_engine(56"mssql+pyodbc://",57connect_args={"odbc_connect": odbc_conn},58)5960@event.listens_for(engine, "do_connect")61def provide_token(dialect, conn_rec, cargs, cparams):62# Fetch a fresh token for every new physical connection — pool refills won't fail after 1h63token = credential.get_token("https://database.windows.net/.default")64token_bytes = token.token.encode("utf-16-le")65token_struct = struct.pack(f"<I{len(token_bytes)}s", len(token_bytes), token_bytes)66cparams["attrs_before"] = {1256: token_struct} # SQL_COPT_SS_ACCESS_TOKEN6768return engine697071engine = create_db_engine()72SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)73```7475### Models7677Create `models.py`:7879```python80from sqlalchemy import Column, Integer, String, Boolean81from database import Base8283class TodoItem(Base):84__tablename__ = "todo_items"8586id = Column(Integer, primary_key=True, index=True)87title = Column(String(200), nullable=False)88is_complete = Column(Boolean, default=False)89```9091### API Endpoints9293Add to `main.py` — do NOT replace existing routes:9495```python96from fastapi import Depends, HTTPException97from sqlalchemy.orm import Session98from database import SessionLocal, engine, Base99from models import TodoItem100from pydantic import BaseModel101102Base.metadata.create_all(bind=engine)103104def get_db():105db = SessionLocal()106try:107yield db108finally:109db.close()110111class TodoCreate(BaseModel):112title: str113is_complete: bool = False114115@app.get("/api/todos")116def list_todos(db: Session = Depends(get_db)):117return db.query(TodoItem).all()118119@app.get("/api/todos/{todo_id}")120def get_todo(todo_id: int, db: Session = Depends(get_db)):121todo = db.query(TodoItem).filter(TodoItem.id == todo_id).first()122if not todo:123raise HTTPException(status_code=404, detail="Not found")124return todo125126@app.post("/api/todos", status_code=201)127def create_todo(todo: TodoCreate, db: Session = Depends(get_db)):128db_todo = TodoItem(**todo.model_dump())129db.add(db_todo)130db.commit()131db.refresh(db_todo)132return db_todo133```134135### Local Development136137For local development without managed identity, use SQL authentication:138139```python140# .env (local only — never commit)141AZURE_SQL_CONNECTION_STRING=mssql+pyodbc://<username>:<password>@localhost/myapp?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes142```143144## Files to Add145146| File | Action |147|------|--------|148| `database.py` | Create — engine, session, managed identity token |149| `models.py` | Create — SQLAlchemy ORM models |150| `main.py` | Modify — add CRUD endpoints + DB dependency |151| `requirements.txt` | Modify — add sqlalchemy, pyodbc, azure-identity |152153## Common Patterns154155- Use `Depends(get_db)` for session lifecycle management156- Use `Base.metadata.create_all()` only for dev; use Alembic migrations in production157- Never store SQL passwords in app settings — use managed identity tokens158