← full-stack-fastapi-template  /  backend/app/api/routes/items.py

1
import uuid
2
from typing import Any
3
4
from fastapi import APIRouter, HTTPException
5
from sqlmodel import col, func, select
6
7
from app.api.deps import CurrentUser, SessionDep
8
from app.models import Item, ItemCreate, ItemPublic, ItemsPublic, ItemUpdate, Message
9
10
router = APIRouter(prefix="/items", tags=["items"])
11
12
13
@router.get("/", response_model=ItemsPublic)
14
def read_items(
15
    session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100
16
) -> Any:
17
    """
18
    Retrieve items.
19
    """
20
21
    if current_user.is_superuser:
22
        count_statement = select(func.count()).select_from(Item)
23
        count = session.exec(count_statement).one()
24
        statement = (
25
            select(Item).order_by(col(Item.created_at).desc()).offset(skip).limit(limit)
26
        )
27
        items = session.exec(statement).all()
28
    else:
29
        count_statement = (
30
            select(func.count())
31
            .select_from(Item)
32
            .where(Item.owner_id == current_user.id)
33
        )
34
        count = session.exec(count_statement).one()
35
        statement = (
36
            select(Item)
37
            .where(Item.owner_id == current_user.id)
38
            .order_by(col(Item.created_at).desc())
39
            .offset(skip)
40
            .limit(limit)
41
        )
42
        items = session.exec(statement).all()
43
44
    items_public = [ItemPublic.model_validate(item) for item in items]
45
    return ItemsPublic(data=items_public, count=count)
46
47
48
@router.get("/{id}", response_model=ItemPublic)
49
def read_item(session: SessionDep, current_user: CurrentUser, id: uuid.UUID) -> Any:
50
    """
51
    Get item by ID.
52
    """
53
    item = session.get(Item, id)
54
    if not item:
55
        raise HTTPException(status_code=404, detail="Item not found")
56
    if not current_user.is_superuser and (item.owner_id != current_user.id):
57
        raise HTTPException(status_code=403, detail="Not enough permissions")
58
    return item
59
60
61
@router.post("/", response_model=ItemPublic)
62
def create_item(
63
    *, session: SessionDep, current_user: CurrentUser, item_in: ItemCreate
64
) -> Any:
65
    """
66
    Create new item.
67
    """
68
    item = Item.model_validate(item_in, update={"owner_id": current_user.id})
69
    session.add(item)
70
    session.commit()
71
    session.refresh(item)
72
    return item
73
74
75
@router.put("/{id}", response_model=ItemPublic)
76
def update_item(
77
    *,
78
    session: SessionDep,
79
    current_user: CurrentUser,
80
    id: uuid.UUID,
81
    item_in: ItemUpdate,
82
) -> Any:
83
    """
84
    Update an item.
85
    """
86
    item = session.get(Item, id)
87
    if not item:
88
        raise HTTPException(status_code=404, detail="Item not found")
89
    if not current_user.is_superuser and (item.owner_id != current_user.id):
90
        raise HTTPException(status_code=403, detail="Not enough permissions")
91
    update_dict = item_in.model_dump(exclude_unset=True)
92
    item.sqlmodel_update(update_dict)
93
    session.add(item)
94
    session.commit()
95
    session.refresh(item)
96
    return item
97
98
99
@router.delete("/{id}")
100
def delete_item(
101
    session: SessionDep, current_user: CurrentUser, id: uuid.UUID
102
) -> Message:
103
    """
104
    Delete an item.
105
    """
106
    item = session.get(Item, id)
107
    if not item:
108
        raise HTTPException(status_code=404, detail="Item not found")
109
    if not current_user.is_superuser and (item.owner_id != current_user.id):
110
        raise HTTPException(status_code=403, detail="Not enough permissions")
111
    session.delete(item)
112
    session.commit()
113
    return Message(message="Item deleted successfully")
114