Web Commerce - Middleware
Location: api/nextango/apps/web_commerce/middleware.py
Last Updated: 2026-07-08
Overview
CartValidationMiddleware runs on every request to keep request.session['cart_id'] pointed at a cart the current session actually owns, clearing or claiming it before any view runs. It is registered in MIDDLEWARE after the session middleware (settings/base.py:170) and runs in both DEBUG and production.
CartValidationMiddleware
Source: middleware.py:10-79
Identity resolution
The middleware resolves identity via SessionService.resolve_web_session() (cookie-only: the valid, unexpired WebSession for the current Django session_key), not the session-stored storefront_session_id, which could be stale, expired, or point at a foreign session. If no valid WebSession resolves, cart_id is cleared from the session immediately and processing stops.
Validation logic
When request.session['cart_id'] is set and a WebSession resolves:
- Cart does not exist: clear
cart_idfrom the session (logged at WARNING). - Cart's
web_session_idisNone(a legacy cart whose FK was never backfilled, named by this session): claim it atomically onto the resolvedweb_sessionvia a conditionalUPDATEguarded byweb_session__isnull=True, status=ACTIVE, so exactly one concurrent request wins the claim and a non-ACTIVEcart is never claimed. If the claim fails (already claimed by a concurrent request, or the cart is notACTIVE),cart_idis cleared (logged at INFO). - Cart is owned by a different
web_session: clearcart_idfrom the session (logged at WARNING). The pointer is never reassigned to a different owner. - Cart status is not
ACTIVE: clearcart_idfrom the session (logged at INFO).
If none of the above trigger, the session's cart_id is left untouched.
Why this exists
Cart references can become orphaned: the cart was deleted, the session's identity changed across login/logout, the cart completed checkout and is no longer ACTIVE, or a legacy cart predates the web_session FK backfill. Rather than let a downstream view fail with an ownership error, the middleware normalizes request.session['cart_id'] before the view runs so views can rely on it (or on the ownership-based authorization in views.py, which re-checks independently) without repeating this logic.
Related Documentation
- Models:
CheckoutSession,CheckoutReservationContext - Transactions Models:
Cartand itsweb_sessionFK - Services:
SessionService,CartService - Views: cart API endpoints and their ownership-based authorization