A Django storefront with a real account system, catalog with categories and search, session-based cart/wishlist, and a checkout flow that creates real orders. Built as a portfolio project, structured so it can grow into a real store without a rewrite.
| Storefront | Product detail | Cart |
|---|---|---|
![]() |
![]() |
![]() |
The project is split into focused apps instead of one monolithic app:
| App | Responsibility |
|---|---|
catalog |
Products, categories, search/filter, browsing, read-only REST API |
cart |
Session-based cart & wishlist (shared by templates and checkout) |
orders |
Checkout, Order/OrderItem models, payment gateway abstraction, order history |
accounts |
Registration, login/logout, profile (built on Django's auth.User) |
Shared templates live in templates/ (currently just base.html); each app
owns its own templates under <app>/templates/<app>/.
- Pluggable payment gateway (
orders/payments.py):MockPaymentGatewayalways succeeds so checkout works with zero external accounts. AStripePaymentGatewayimplementing the same interface is ready to go — see "Path to production" below. - Order line-item snapshots:
OrderItemstoresproduct_nameandunit_priceat time of purchase, so historical orders stay accurate even if a product is later renamed, repriced, or deleted. - Optional Celery: order-confirmation emails go through
orders/emails.py, which tries to dispatch a Celery task and transparently falls back to sending synchronously if Celery isn't installed/configured (CELERY_TASK_ALWAYS_EAGERis on by default). No broker required for local dev. - Read-only REST API (
/api/products/,/api/categories/) built with Django REST Framework — a starting point for a future mobile app or decoupled frontend.
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # macOS/Linux
pip install -r requirements.txt # core -- enough to run locally
# pip install -r requirements-prod.txt # + Postgres, Celery, payments, monitoring
cp .env.example .env # then edit as needed
manage.py doesn't auto-load .env — export the variables yourself, or run
via docker compose (below), which does.
export DJANGO_DEBUG=true # or set in your shell / .env loader
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Visit http://127.0.0.1:8000/ for the storefront and /admin/ for the
Django admin. /api/products/ for the JSON API.
docker compose up --build
docker compose exec web python manage.py migrate
docker compose exec web python manage.py createsuperuser
This runs the app against real Postgres and Redis, plus a Celery worker.
sample_products.sql contains a raw SQL INSERT statement with sample
products. Load it with:
python import_products.py
This deletes all existing products before importing, so it refuses to
run if products already exist unless you pass --force.
python manage.py test
29 tests cover catalog browsing/search/filtering, the product API, cart and wishlist behavior (including edge cases like stock hitting zero mid-cart), the full checkout flow, order ownership/isolation, and registration/login.
CI (.github/workflows/ci.yml) runs lint (ruff), manage.py check, the
test suite, and a dependency vulnerability scan on every push.
| Variable | Default | Notes |
|---|---|---|
DJANGO_SECRET_KEY |
dev-only insecure key | Always set a real secret in production |
DJANGO_DEBUG |
false |
Set true for local dev |
DJANGO_ALLOWED_HOSTS |
localhost,127.0.0.1 |
Comma-separated |
DATABASE_URL |
unset (uses SQLite) | postgres://user:pass@host:5432/db |
EMAIL_BACKEND |
console backend | Point at real SMTP in production |
PAYMENT_GATEWAY |
mock |
Set stripe once ready to take real payments |
STRIPE_SECRET_KEY / STRIPE_PUBLISHABLE_KEY |
unset | Required if PAYMENT_GATEWAY=stripe |
CELERY_BROKER_URL |
unset (tasks run synchronously) | e.g. redis://localhost:6379/0 |
SENTRY_DSN |
unset (error tracking disabled) |
See .env.example for a ready-to-copy template.
This is deliberately a portfolio-ready demo, not a deployed store. Here's what's already built vs. what still needs a real account/decision before you take real money and real user data:
Already wired up, just needs configuration:
- Postgres via
DATABASE_URL(SQLite is fine for a demo, not for concurrent production writes) - Stripe payments (
orders/payments.py— setPAYMENT_GATEWAY=stripe+ API keys) - Celery + Redis for background email (set
CELERY_BROKER_URL) - Sentry error tracking (set
SENTRY_DSN) - Production security headers (HSTS, secure cookies — auto-enabled when
DJANGO_DEBUG=false) - Static file serving via WhiteNoise (works as-is; move to S3/CDN once traffic justifies it)
Needs a decision/real infra before going live:
- Real hosting (Render, Railway, Fly.io, AWS, etc.) + a domain + HTTPS certificate
- A persistent per-user cart (current cart is session-based; fine for a demo, but logged-in users would expect their cart to follow them across devices)
- Guest checkout (checkout currently requires an account)
- Order fulfillment/shipping integration, refunds/cancellation flow
- Product images hosted properly (currently raw URLs in a JSON field —
fine for a demo, but a real store wants uploaded images via
ImageField- object storage)
- 2FA for staff/admin accounts, and a review of
django-ratelimit's default in-memory cache backend (swap for Redis in production so rate limits are shared across workers)


