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