Added full CRUD operations for filaments
This commit is contained in:
@@ -3,12 +3,14 @@
|
||||
from typing import Annotated, Optional, Union
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic.error_wrappers import ErrorWrapper
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from spoolson.api.v1.models import Filament, Vendor
|
||||
from spoolson.api.v1.models import Filament, Message
|
||||
from spoolson.database import filament
|
||||
from spoolson.database.database import get_db_session
|
||||
from spoolson.database.filament import create_filament
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/filament",
|
||||
@@ -37,30 +39,23 @@ class FilamentParameters(BaseModel):
|
||||
comment: Optional[str] = Field(max_length=1024, description="Free text comment about this filament type.")
|
||||
|
||||
|
||||
class FilamentUpdateParameters(FilamentParameters):
|
||||
density: Optional[float] = Field(gt=0, description="The density of this filament in g/cm3.")
|
||||
diameter: Optional[float] = Field(gt=0, description="The diameter of this filament in mm.")
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def find(_vendor: Union[int, None] = None) -> list[Filament]:
|
||||
return []
|
||||
|
||||
|
||||
@router.get("/{filament_id}")
|
||||
async def get(_filament_id: int) -> Filament:
|
||||
return Filament(
|
||||
id=0,
|
||||
name=None,
|
||||
vendor=Vendor(
|
||||
id=0,
|
||||
name="asdf",
|
||||
comment=None,
|
||||
),
|
||||
material=None,
|
||||
price=None,
|
||||
density=1,
|
||||
diameter=1,
|
||||
weight=None,
|
||||
spool_weight=None,
|
||||
article_number=None,
|
||||
comment=None,
|
||||
)
|
||||
async def get(
|
||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||
filament_id: int,
|
||||
) -> Filament:
|
||||
db_item = await filament.get_by_id(db, filament_id)
|
||||
return Filament.from_db(db_item)
|
||||
|
||||
|
||||
@router.post("/")
|
||||
@@ -68,7 +63,7 @@ async def create(
|
||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||
body: FilamentParameters,
|
||||
) -> Filament:
|
||||
db_item = await create_filament(
|
||||
db_item = await filament.create(
|
||||
db=db,
|
||||
density=body.density,
|
||||
diameter=body.diameter,
|
||||
@@ -85,27 +80,32 @@ async def create(
|
||||
return Filament.from_db(db_item)
|
||||
|
||||
|
||||
@router.put("/{filament_id}")
|
||||
async def update() -> Filament:
|
||||
return Filament(
|
||||
id=0,
|
||||
name=None,
|
||||
vendor=Vendor(
|
||||
id=0,
|
||||
name="asdf",
|
||||
comment=None,
|
||||
),
|
||||
material=None,
|
||||
price=None,
|
||||
density=1,
|
||||
diameter=1,
|
||||
weight=None,
|
||||
spool_weight=None,
|
||||
article_number=None,
|
||||
comment=None,
|
||||
@router.patch("/{filament_id}")
|
||||
async def update(
|
||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||
filament_id: int,
|
||||
body: FilamentUpdateParameters,
|
||||
) -> Filament:
|
||||
patch_data = body.dict(exclude_unset=True)
|
||||
|
||||
if "density" in patch_data and body.density is None:
|
||||
raise RequestValidationError([ErrorWrapper(ValueError("density cannot be unset"), ("query", "density"))])
|
||||
if "diameter" in patch_data and body.diameter is None:
|
||||
raise RequestValidationError([ErrorWrapper(ValueError("diameter cannot be unset"), ("query", "diameter"))])
|
||||
|
||||
db_item = await filament.update(
|
||||
db=db,
|
||||
filament_id=filament_id,
|
||||
data=patch_data,
|
||||
)
|
||||
|
||||
return Filament.from_db(db_item)
|
||||
|
||||
|
||||
@router.delete("/{filament_id}")
|
||||
async def delete() -> None:
|
||||
pass
|
||||
async def delete(
|
||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||
filament_id: int,
|
||||
) -> Message:
|
||||
await filament.delete(db, filament_id)
|
||||
return Message(message="Success!")
|
||||
|
||||
@@ -8,6 +8,10 @@ from pydantic import BaseModel, Field
|
||||
from spoolson.database import models
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
message: str = Field()
|
||||
|
||||
|
||||
class Vendor(BaseModel):
|
||||
id: int = Field(description="Unique internal ID of this vendor.")
|
||||
name: str = Field(max_length=64, description="Vendor name.")
|
||||
|
||||
@@ -7,7 +7,7 @@ from starlette.responses import Response
|
||||
|
||||
from spoolson.exceptions import ItemNotFoundError
|
||||
|
||||
from . import filament, spool, vendor
|
||||
from . import filament, models, spool, vendor
|
||||
|
||||
# ruff: noqa: D103
|
||||
|
||||
@@ -15,6 +15,7 @@ app = FastAPI(
|
||||
title="Spoolson REST API v1",
|
||||
version="1.0.0",
|
||||
root_path_in_servers=False,
|
||||
responses={404: {"model": models.Message}},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ from typing import Optional
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from spoolson.database import models, vendor
|
||||
from spoolson.exceptions import ItemNotFoundError
|
||||
|
||||
|
||||
async def create_filament(
|
||||
async def create(
|
||||
*,
|
||||
db: AsyncSession,
|
||||
density: float,
|
||||
@@ -41,3 +42,37 @@ async def create_filament(
|
||||
db.add(db_item)
|
||||
await db.flush()
|
||||
return db_item
|
||||
|
||||
|
||||
async def get_by_id(db: AsyncSession, filament_id: int) -> models.Filament:
|
||||
"""Get a filament object from the database by the unique ID."""
|
||||
filament = await db.get(models.Filament, filament_id)
|
||||
if filament is None:
|
||||
raise ItemNotFoundError(f"No filament with ID {filament_id} found.")
|
||||
return filament
|
||||
|
||||
|
||||
async def update(
|
||||
*,
|
||||
db: AsyncSession,
|
||||
filament_id: int,
|
||||
data: dict,
|
||||
) -> models.Filament:
|
||||
"""Update the fields of a filament object."""
|
||||
filament = await get_by_id(db, filament_id)
|
||||
for k, v in data.items():
|
||||
if k == "vendor_id":
|
||||
if v is None:
|
||||
filament.vendor = None
|
||||
else:
|
||||
filament.vendor = await vendor.get_by_id(db, v)
|
||||
else:
|
||||
setattr(filament, k, v)
|
||||
await db.flush()
|
||||
return filament
|
||||
|
||||
|
||||
async def delete(db: AsyncSession, filament_id: int) -> None:
|
||||
"""Delete a filament object."""
|
||||
filament = await get_by_id(db, filament_id)
|
||||
await db.delete(filament)
|
||||
|
||||
Reference in New Issue
Block a user