python / intermediate
Snippet
Django Session-Based Shopping Cart Pattern
This pattern implements a shopping cart using Django's session framework without database dependencies. Sessions store cart data server-side with a session key stored in a cookie. The modified=True flag ensures the session is saved even when mutable objects like dictionaries are modified. This approach works well for anonymous users and can be extended to persist for logged-in users.
snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from django.shortcuts import render, redirectfrom django.views.decorators.http import require_POSTfrom django.contrib.sessions.backends.db import SessionStoredef get_cart(request):cart = request.session.get('cart', {})return cartdef save_cart(request, cart):request.session['cart'] = cartrequest.session.modified = True@require_POSTdef add_to_cart(request, product_id):cart = get_cart(request)quantity = int(request.POST.get('quantity', 1))if product_id in cart:cart[product_id]['quantity'] += quantityelse:cart[product_id] = {'quantity': quantity,'added_at': request.session.session_key}save_cart(request, cart)return redirect('cart_view')@require_POSTdef update_cart(request, product_id):cart = get_cart(request)quantity = int(request.POST.get('quantity', 1))if quantity > 0:cart[product_id]['quantity'] = quantityelse:cart.pop(product_id, None)save_cart(request, cart)return redirect('cart_view')def cart_view(request):cart = get_cart(request)total_items = sum(item['quantity'] for item in cart.values())context = {'cart': cart,'total_items': total_items}return render(request, 'cart.html', context)
django
Breakdown
1
def get_cart(request):
Helper function to retrieve cart from session with default empty dict
2
cart = request.session.get('cart', {})
Get cart key from session, return empty dict if not exists
3
request.session.modified = True
Critical flag: tells Django session middleware to save even with mutable data
4
@require_POST
Decorator that rejects GET requests, ensures POST method only
5
if product_id in cart:
Check if product already exists in cart for update vs add logic
6
cart[product_id]['quantity'] += quantity
Increment quantity for existing product
7
else: cart[product_id] = {...}
Add new product entry with quantity and timestamp
8
if quantity > 0: ... else: cart.pop(...)
Remove item from cart if quantity becomes zero or negative