diff --git a/index.html b/index.html
new file mode 100644
index 0000000..32ad87b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+ Items CRUD App
+
+
+
+ Items List (CRUD)
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.py b/main.py
index 1a6e02d..9da9e37 100644
--- a/main.py
+++ b/main.py
@@ -1,20 +1,28 @@
from fastapi import FastAPI, Depends, HTTPException
+from fastapi_versioning import VersionedFastAPI, version
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
+from sqlalchemy.exc import NoResultFound
from pydantic import BaseModel
from typing import List
from models import Base, Item as ItemModel
from database import engine, SessionLocal
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.staticfiles import StaticFiles
+from fastapi_versioning import VersionedFastAPI
+from fastapi_versioning import version
app = FastAPI()
-# Create tables
+
+
@app.on_event("startup")
async def on_startup():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
+# Pydantic Schemas
class ItemCreate(BaseModel):
name: str
description: str = None
@@ -25,31 +33,76 @@ class ItemRead(ItemCreate):
class Config:
orm_mode = True
+# Dependency
async def get_session() -> AsyncSession:
async with SessionLocal() as session:
yield session
@app.get("/")
+@version(1)
def read_root():
- return "TODO app"
+ return "Items app"
+
+@app.get("/")
+@version(2)
+def read_root():
+ return "Items v2 app"
@app.post("/items/", response_model=ItemRead)
+@version(1)
async def create_item(item: ItemCreate, session: AsyncSession = Depends(get_session)):
- return "todo"
+ db_item = ItemModel(name=item.name, description=item.description)
+ session.add(db_item)
+ await session.commit()
+ await session.refresh(db_item)
+ return db_item
@app.get("/items/", response_model=List[ItemRead])
+@version(1)
async def read_items(session: AsyncSession = Depends(get_session)):
result = await session.execute(select(ItemModel))
return result.scalars().all()
@app.get("/items/{item_id}", response_model=ItemRead)
+@version(1)
async def read_item(item_id: int, session: AsyncSession = Depends(get_session)):
- return "todo"
+ result = await session.execute(select(ItemModel).where(ItemModel.id == item_id))
+ item = result.scalar_one_or_none()
+ if not item:
+ raise HTTPException(status_code=404, detail="Item not found")
+ return item
@app.put("/items/{item_id}", response_model=ItemRead)
+@version(1)
async def update_item(item_id: int, item: ItemCreate, session: AsyncSession = Depends(get_session)):
- return "todo"
+ result = await session.execute(select(ItemModel).where(ItemModel.id == item_id))
+ db_item = result.scalar_one_or_none()
+ if not db_item:
+ raise HTTPException(status_code=404, detail="Item not found")
+ db_item.name = item.name
+ db_item.description = item.description
+ await session.commit()
+ await session.refresh(db_item)
+ return db_item
@app.delete("/items/{item_id}")
+@version(1)
async def delete_item(item_id: int, session: AsyncSession = Depends(get_session)):
- return "todo"
\ No newline at end of file
+ result = await session.execute(select(ItemModel).where(ItemModel.id == item_id))
+ db_item = result.scalar_one_or_none()
+ if not db_item:
+ raise HTTPException(status_code=404, detail="Item not found")
+ await session.delete(db_item)
+ await session.commit()
+ return {"detail": "Item deleted"}
+
+
+app = VersionedFastAPI(app, version_format='{major}', prefix_format='/v{major}')
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+app.mount("/", StaticFiles(directory=".", html=True), name="static")
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 2dcc48d..f3e44b3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
fastapi
uvicorn[standard]
sqlalchemy>=2.0
-aiosqlite
\ No newline at end of file
+aiosqlite
+fastapi-versioning
diff --git a/test.db b/test.db
index 0d4a1bb..5758e86 100644
Binary files a/test.db and b/test.db differ