From d4254ac086c35b88952ddb0e7f8f4c3f6ceac42c Mon Sep 17 00:00:00 2001 From: Ali Asadi Date: Mon, 31 Aug 2026 12:01:38 +0330 Subject: [PATCH] Split CartItemView so swagger stops showing broken cart endpoints CartItemView was registered on both /cart/items/ and /cart/items/{item_uuid}/, so swagger listed POST/PATCH/DELETE on both paths even though 3 of those 6 combinations raised a TypeError at runtime (missing/unexpected item_uuid). Split into CartItemView (POST, list path) and CartItemDetailView (PATCH/DELETE, detail path). Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 1 + apps/orders/urls.py | 3 ++- apps/orders/views.py | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0205674..d7ee26a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - `GET /api/v1/stores/` — documented the `category`, `neighborhood`, `search`, `lat`, and `lng` query params for drf-spectacular so they render in swagger. The filtering itself already worked; only the OpenAPI schema was missing them (`apps/stores/views.py`). - `GET /api/v1/products/` — same issue: documented the existing `store`, `category`, and `search` query params for swagger (`apps/catalog/views.py`). +- Cart items: `CartItemView` was registered on both `/api/v1/cart/items/` and `/api/v1/cart/items/{item_uuid}/`, so swagger showed POST/PATCH/DELETE on both paths — 3 of those 6 combinations crashed with a `TypeError` at runtime (`item_uuid` missing or unexpected). Split into `CartItemView` (POST only, list path) and `CartItemDetailView` (PATCH/DELETE only, detail path) so swagger only shows the combinations that actually work (`apps/orders/views.py`, `apps/orders/urls.py`). ### Added - `GET /api/v1/cities/?search=` — search cities by name (`apps/locations/views.py`); previously no text search existed. diff --git a/apps/orders/urls.py b/apps/orders/urls.py index 365d66d..933de75 100644 --- a/apps/orders/urls.py +++ b/apps/orders/urls.py @@ -2,6 +2,7 @@ from django.urls import path from rest_framework.routers import DefaultRouter from .views import ( + CartItemDetailView, CartItemView, CartView, CheckoutView, @@ -23,5 +24,5 @@ urlpatterns = router.urls + [ path('checkout/', CheckoutView.as_view(), name='checkout'), path('cart/', CartView.as_view(), name='cart'), path('cart/items/', CartItemView.as_view(), name='cart-items'), - path('cart/items//', CartItemView.as_view(), name='cart-item-detail'), + path('cart/items//', CartItemDetailView.as_view(), name='cart-item-detail'), ] diff --git a/apps/orders/views.py b/apps/orders/views.py index a7ba204..fd1465a 100644 --- a/apps/orders/views.py +++ b/apps/orders/views.py @@ -47,7 +47,7 @@ class CartView(APIView): class CartItemView(APIView): - """Add/update/remove a single product line in the authenticated user's cart.""" + """Add a product line to the authenticated user's cart.""" schema_tags = ['Cart'] serializer_class = CartItemWriteSerializer @@ -73,6 +73,15 @@ class CartItemView(APIView): return Response(CartItemSerializer(item).data, status=status.HTTP_201_CREATED) + +class CartItemDetailView(APIView): + """Update/remove a single product line in the authenticated user's cart.""" + + schema_tags = ['Cart'] + serializer_class = CartItemWriteSerializer + permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements] + required_alternate_scopes = {} + @extend_schema(responses=CartItemSerializer) def patch(self, request, item_uuid): item = get_object_or_404(CartItem, uuid=item_uuid, cart__user=request.user) -- 2.45.3