In today’s digital economy, building a secure and scalable e-commerce platform has never been easier — especially with Django, one of the most powerful Python web frameworks, and Stripe, a developer-friendly payment gateway trusted by millions worldwide. In this tutorial, you’ll learn how to create a complete e-commerce website using Django 5.2.7 and integrate Stripe Checkout to handle payments safely and efficiently.
We’ll start from scratch by setting up a Django project, designing models for products and orders, implementing a session-based shopping cart, and connecting it to Stripe for payment processing. You’ll also learn how to handle webhooks to confirm payments automatically and update order statuses in real time. By the end of this guide, you’ll have a fully functional online store that you can deploy to production with secure HTTPS and environment-based configuration.
Whether you’re a Python developer looking to expand your skills or an entrepreneur aiming to launch your online business, this step-by-step tutorial will give you the foundation to build, customize, and scale your own e-commerce solution using Django and Stripe.
Prerequisites & versions
-
Python 3.11+ (works with Python 3.11–3.13; confirm your environment).
-
Django 5.2.7.
-
Stripe Python SDK v13.0.0.
-
A Stripe account (test keys are enough for local dev).
-
(Optional) PostgreSQL for production.
Section 1: Project Setup and Dependencies Installation
In this section, you’ll set up a new Django project, create a virtual environment, and install the dependencies required for building the e-commerce application with Stripe integration.
1.1 Create a New Project Folder
Start by creating a directory for your project and navigating into it:
mkdir django-stripe-ecommerce
cd django-stripe-ecommerce
1.2 Create a Virtual Environment
Create and activate a virtual environment (recommended for isolating dependencies):
For macOS/Linux:
python3 -m venv venv
source venv/bin/activate
For Windows:
python -m venv venv
venv\Scripts\activate
1.3 Install Required Packages
Now install Django and Stripe SDK:
pip install django==5.0.7 stripe==10.4.0 python-dotenv
Here’s what each package does:
-
Django – the main web framework.
-
Stripe – official Stripe Python SDK for creating checkout sessions and handling webhooks.
-
python-dotenv – used to load environment variables from a
.env
file.
1.4 Create Django Project and Apps
Generate the Django project:
django-admin startproject django_stripe_ecommerce .
Then, create the main apps for this project:
python manage.py startapp products
python manage.py startapp cart
python manage.py startapp orders
1.5 Configure Installed Apps
Open django_stripe_ecommerce/settings.py
and add the new apps:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Local apps
'products',
'cart',
'orders',
]
1.6 Configure Static and Template Paths
Still in settings.py
, update the TEMPLATES
and STATICFILES_DIRS
sections to recognize global directories:
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'cart.context_processors.cart_total', # custom cart processor
],
},
},
]
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
1.7 Create .env
for Secrets
Create a .env
file in the project root and add your Stripe API keys (replace with your real keys from the Stripe Dashboard):
STRIPE_PUBLISHABLE_KEY=pk_test_123456789
STRIPE_SECRET_KEY=sk_test_123456789
DEBUG=True
Then, load these in settings.py
:
from dotenv import load_dotenv
load_dotenv()
import os
STRIPE_PUBLISHABLE_KEY = os.getenv('STRIPE_PUBLISHABLE_KEY')
STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY')
DEBUG = os.getenv('DEBUG') == 'True'
1.8 Run Initial Migrations and Start Server
Finally, apply migrations and run the development server to confirm everything is working:
python manage.py migrate
python manage.py runserver
You should see the Django welcome page at:
✅ At this point:
Your Django project is ready with basic structure, environment configuration, and apps created. Next, we’ll build the Product Model and Display Pages to show your e-commerce catalog.
Section 2: Creating the Product Model and Display Page
In this section, we’ll define a Product
model, register it in the admin panel, and create a simple product listing page to display all products on the front end.
2.1 Define the Product Model
Open the file products/models.py
and add the following code:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
image = models.ImageField(upload_to='products/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
@property
def formatted_price(self):
return f"${self.price:.2f}"
📝 Explanation:
-
name
,description
,price
, andimage
represent essential product information. -
formatted_price
is a helper property to display prices nicely in templates.
2.2 Register Product in Admin
Open products/admin.py
and register the model so you can manage products easily from Django Admin:
from django.contrib import admin
from .models import Product
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'created_at')
search_fields = ('name',)
Now run the following commands to apply the database migration and create an admin user:
python -m pip install Pillow
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
Follow the prompts to set up your superuser credentials.
Then start the server and log in to the admin site:
👉 http://127.0.0.1:8000/admin/
You can now add new products using the admin interface.
2.3 Create Product Views and URLs
Open products/views.py
and create a simple view to display all products:
from django.shortcuts import render
from .models import Product
def product_list(request):
products = Product.objects.all().order_by('-created_at')
return render(request, 'products/product_list.html', {'products': products})
Then, create a new file products/urls.py
:
from django.urls import path
from . import views
urlpatterns = [
path('', views.product_list, name='product_list'),
]
Now, include this in your main project django_stripe_ecommerce/urls.py
:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('products.urls')),
]
2.4 Create Product List Template
Create a template at:
products/templates/products/product_list.html
Add the following HTML:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container">
<h2 class="text-center mt-4">Our Products</h2>
<div class="product-grid">
{% for product in products %}
<div class="product-card">
<img src="{{ product.image.url }}" alt="{{ product.name }}" />
<h3>{{ product.name }}</h3>
<p>{{ product.description|truncatechars:100 }}</p>
<p class="price">{{ product.formatted_price }}</p>
<button class="add-to-cart">Add to Cart</button>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
2.5 Add Basic Product Styles
Create the file:
products/static/products/css/products.css
Add simple styles:
.container {
width: 90%;
margin: 0 auto;
}
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 20px;
margin-top: 30px;
}
.product-card {
background: #fff;
border: 1px solid #ddd;
border-radius: 10px;
padding: 15px;
text-align: center;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: transform 0.2s;
}
.product-card:hover {
transform: scale(1.03);
}
.product-card img {
max-width: 100%;
border-radius: 10px;
}
.price {
font-weight: bold;
color: #333;
}
.add-to-cart {
background: #0a74da;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
}
.add-to-cart:hover {
background: #095aba;
}
Then include this stylesheet in your root/templates/base.html
(under <head>
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>{% block title %}My Django Shop{% endblock %}</title>
<meta
name="description"
content="{% block meta_desc %}A simple Django e-commerce demo with Stripe Checkout.{% endblock %}"
/>
<!-- Styles -->
<link rel="stylesheet" href="{% static 'css/styles.css' %}" />
<link rel="stylesheet" href="{% static 'products/css/products.css' %}" />
<!-- Stripe.js (loaded early) -->
<script src="https://js.stripe.com/v3/"></script>
{% block head_extra %}{% endblock %}
</head>
<body>
<header class="site-header">
<div class="container header-inner">
<a class="brand" href="{% url 'store:product_list' %}">Djamware Shop</a>
<nav class="nav">
<a href="{% url 'store:product_list' %}">Products</a>
<a href="{% url 'store:cart_detail' %}" id="cart-link"
>Cart (<span id="cart-count"
>{{ request.session.cart|length|default:0 }}</span
>)</a
>
</nav>
</div>
</header>
<main class="container">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="msg {{ message.tags }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %} {% block content %}{% endblock %}
</main>
<footer class="site-footer">
<div class="container">
© {{ now.year }} Djamware Shop · Built with Django & Stripe
</div>
</footer>
<!-- Shared JS (CSRF helpers, small UI utilities) -->
<script>
// Simple helper to read cookie (Django CSRF cookie name 'csrftoken')
function getCookie(name) {
const v = document.cookie
.split("; ")
.find((row) => row.startsWith(name + "="));
return v ? decodeURIComponent(v.split("=")[1]) : null;
}
const CSRF_TOKEN = getCookie("csrftoken");
</script>
<script src="{% static 'js/cart.js' %}"></script>
<script src="{% static 'js/checkout.js' %}"></script>
{% block body_extra %}{% endblock %}
</body>
</html>
✅ At this point:
You now have:
-
A Product model stored in the database.
-
An Admin interface to manage products.
-
A Public product listing page showing images, names, and prices.
Section 3: Building the Shopping Cart Functionality
Now that your products are displayed, let’s make the e-commerce site interactive by allowing users to add products to a shopping cart, view cart details, update quantities, and remove items — all stored in their Django session.
3.1 Create a cart.py
Helper File
Inside your cart/
app, create a new file:
cart/cart.py
Add the following class to manage the shopping cart logic:
from decimal import Decimal
from django.conf import settings
from products.models import Product
class Cart:
def __init__(self, request):
self.session = request.session
cart = self.session.get('cart')
if not cart:
cart = self.session['cart'] = {}
self.cart = cart
def add(self, product_id, quantity=1):
product = Product.objects.get(id=product_id)
product_id_str = str(product_id)
if product_id_str not in self.cart:
self.cart[product_id_str] = {
'name': product.name,
'price': str(product.price),
'quantity': 0,
'image': product.image.url if product.image else '',
}
self.cart[product_id_str]['quantity'] += quantity
self.save()
def remove(self, product_id):
product_id_str = str(product_id)
if product_id_str in self.cart:
del self.cart[product_id_str]
self.save()
def clear(self):
self.session['cart'] = {}
self.session.modified = True
def save(self):
self.session.modified = True
def __iter__(self):
for item in self.cart.values():
item['price'] = Decimal(item['price'])
item['total_price'] = item['price'] * item['quantity']
yield item
def get_total_price(self):
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
📝 Explanation:
-
add()
— adds a product or increases quantity. -
remove()
— removes a product from the cart. -
clear()
— empties the cart. -
__iter__()
— allows easy looping in templates. -
get_total_price()
— calculates total cost. -
The cart is stored in
request.session
, so it’s persistent per user session.
3.2 Create Cart Views
Open cart/views.py
and add the following functions:
from django.shortcuts import render, redirect, get_object_or_404
from products.models import Product
from .cart import Cart
def cart_detail(request):
cart = Cart(request)
return render(request, 'cart/cart_detail.html', {'cart': cart})
def cart_add(request, product_id):
cart = Cart(request)
cart.add(product_id=product_id)
return redirect('cart_detail')
def cart_remove(request, product_id):
cart = Cart(request)
cart.remove(product_id=product_id)
return redirect('cart_detail')
def cart_clear(request):
cart = Cart(request)
cart.clear()
return redirect('cart_detail')
3.3 Create Cart URLs
Create a new file cart/urls.py
:
from django.urls import path
from . import views
urlpatterns = [
path('', views.cart_detail, name='cart_detail'),
path('add/<int:product_id>/', views.cart_add, name='cart_add'),
path('remove/<int:product_id>/', views.cart_remove, name='cart_remove'),
path('clear/', views.cart_clear, name='cart_clear'),
]
Then include these URLs in your main django_stripe_ecommerce/urls.py
:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('products.urls')),
path('cart/', include('cart.urls')),
]
3.4 Create Cart Template
Create the file:
cart/templates/cart/cart_detail.html
Add this HTML:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container mt-5">
<h2 class="text-center mb-4">Your Shopping Cart</h2>
{% if cart|length == 0 %}
<p class="text-center">Your cart is empty.</p>
{% else %}
<table class="cart-table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for item in cart %}
<tr>
<td>
<img src="{{ item.image }}" alt="{{ item.name }}" class="cart-img">
{{ item.name }}
</td>
<td>{{ item.quantity }}</td>
<td>${{ item.price }}</td>
<td>${{ item.total_price }}</td>
<td><a href="{% url 'cart_remove' forloop.counter %}" class="remove">Remove</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="cart-total">
<h3>Total: ${{ cart.get_total_price }}</h3>
<a href="{% url 'cart_clear' %}" class="btn-clear">Clear Cart</a>
<a href="{% url 'checkout' %}" class="btn-checkout">Proceed to Checkout</a>
</div>
{% endif %}
</div>
{% endblock %}
3.5 Add Styles for Cart Page
Create:
cart/static/cart/css/cart.css
.cart-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.cart-table th,
.cart-table td {
padding: 12px;
border: 1px solid #ddd;
text-align: center;
}
.cart-img {
width: 50px;
border-radius: 5px;
margin-right: 10px;
}
.cart-total {
margin-top: 30px;
text-align: right;
}
.btn-checkout,
.btn-clear {
background: #0a74da;
color: #fff;
padding: 10px 15px;
text-decoration: none;
border-radius: 5px;
margin-left: 10px;
}
.btn-clear {
background: #dc3545;
}
Include this file in base.html
or only in the cart page if preferred.
3.6 Update Product Buttons to Add to Cart
In your products/templates/products/product_list.html
, update the Add to Cart button like this:
<a href="{% url 'cart_add' product.id %}" class="add-to-cart">Add to Cart</a>
✅ At this point:
You now have a fully functional shopping cart that:
-
Stores cart data in sessions
-
Allows adding/removing/clearing items
-
Displays a running total
-
Shows total item count (via context processor)
Section 4: Implementing Stripe Checkout Integration
In this section, we’ll integrate Stripe Checkout into the Django e-commerce app so customers can pay securely with credit or debit cards.
Stripe Checkout handles all the complex parts — PCI compliance, 3D Secure authentication, and a beautiful, mobile-friendly interface — letting you focus on your app logic.
1. Create a Stripe Account and Get API Keys
-
Go to https://dashboard.stripe.com.
-
Create or log into your Stripe account.
-
Navigate to Developers → API keys.
-
Copy your Publishable key and Secret key — you’ll need both.
2. Install Stripe SDK
Run the following command in your virtual environment:
pip install stripe
3. Configure Stripe Keys in settings.py
Add the following to the bottom of your settings.py
file:
# Stripe configuration
STRIPE_PUBLIC_KEY = 'your-publishable-key-here'
STRIPE_SECRET_KEY = 'your-secret-key-here'
STRIPE_SUCCESS_URL = 'http://127.0.0.1:8000/success/'
STRIPE_CANCEL_URL = 'http://127.0.0.1:8000/cancel/'
💡 In production, you’ll store these keys in environment variables instead of hardcoding them.
4. Create a New App for Checkout
Let’s keep payment logic clean by creating a new app:
python manage.py startapp payments
Then add it to INSTALLED_APPS
in settings.py
:
INSTALLED_APPS = [
...
'cart',
'store',
'payments',
]
5. Define the Checkout View
Edit payments/views.py
:
import stripe
from django.conf import settings
from django.shortcuts import redirect, render
from django.views import View
stripe.api_key = settings.STRIPE_SECRET_KEY
class CreateCheckoutSessionView(View):
def post(self, request, *args, **kwargs):
cart = request.session.get('cart', {})
line_items = []
for product_id, item in cart.items():
line_items.append({
'price_data': {
'currency': 'usd',
'product_data': {'name': item['name']},
'unit_amount': int(item['price'] * 100),
},
'quantity': item['quantity'],
})
session = stripe.checkout.Session.create(
payment_method_types=['card'],
line_items=line_items,
mode='payment',
success_url=settings.STRIPE_SUCCESS_URL,
cancel_url=settings.STRIPE_CANCEL_URL,
)
return redirect(session.url, code=303)
6. Add Success and Cancel Views
Still in payments/views.py
, add:
def success_view(request):
request.session['cart'] = {} # clear the cart after payment
return render(request, 'payments/success.html')
def cancel_view(request):
return render(request, 'payments/cancel.html')
7. Add Payment URLs
Create a new file payments/urls.py
:
from django.urls import path
from .views import CreateCheckoutSessionView, success_view, cancel_view
urlpatterns = [
path('create-checkout-session/', CreateCheckoutSessionView.as_view(), name='create_checkout_session'),
path('success/', success_view, name='success'),
path('cancel/', cancel_view, name='cancel'),
]
Include it in the main urls.py
(e.g., in django_stripe_ecommerce/urls.py
):
path('', include('store.urls')),
path('cart/', include('cart.urls')),
path('payments/', include('payments.urls')),
8. Create Payment Templates
In templates/payments/success.html
:
{% extends "base.html" %}
{% block content %}
<div class="text-center mt-5">
<h2>Payment Successful!</h2>
<p>Thank you for your purchase. Your order is being processed.</p>
<a href="/" class="btn btn-primary mt-3">Back to Store</a>
</div>
{% endblock %}
In templates/payments/cancel.html
:
{% extends "base.html" %}
{% block content %}
<div class="text-center mt-5">
<h2>Payment Cancelled</h2>
<p>Your payment was cancelled. You can try again anytime.</p>
<a href="/cart/" class="btn btn-warning mt-3">Return to Cart</a>
</div>
{% endblock %}
9. Add Checkout Button to the Cart Page
Edit your templates/cart/cart_detail.html
(or wherever your cart view is):
<form action="{% url 'create_checkout_session' %}" method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-success mt-3">Checkout with Stripe</button>
</form>
10. Test the Checkout Flow
Run your server:
python manage.py runserver
-
Add items to your cart.
-
Click Checkout with Stripe.
-
You should be redirected to Stripe’s payment page.
-
Use Stripe’s test card numbers (e.g.,
4242 4242 4242 4242
, any future expiry, any CVC). -
After successful payment, you’ll be redirected to
/success/
.
✅ You’ve successfully integrated Stripe Checkout into your Django e-commerce app!
Section 5: Handling Stripe Webhooks and Order Confirmation
1. What Are Webhooks?
A webhook is a message Stripe sends to your server to notify you about important events — such as:
-
checkout.session.completed
→ payment succeeded -
payment_intent.payment_failed
→ payment failed -
charge.refunded
→ refund processed
We’ll handle checkout.session.completed
to mark an order as paid.
2. Create a Webhook Endpoint in Django
Open payments/views.py
and add the following imports and view:
import json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')
endpoint_secret = 'your-webhook-signing-secret' # Replace with your actual secret
event = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError:
# Invalid payload
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError:
# Invalid signature
return HttpResponse(status=400)
# Handle the event
if event['type'] == 'checkout.session.completed':
session = event['data']['object']
handle_successful_payment(session)
return HttpResponse(status=200)
3. Add a Payment Handler Function
Still in payments/views.py
, define handle_successful_payment(session)
:
from store.models import Product
from django.core.mail import send_mail
from django.conf import settings
def handle_successful_payment(session):
# You could retrieve metadata if you attach it to checkout sessions
print(f"Payment was successful for session: {session['id']}")
# Example: send a confirmation email (optional)
send_mail(
subject="Order Confirmation",
message="Your payment was successful. Thank you for your order!",
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=["[email protected]"], # Replace with dynamic user email
fail_silently=True,
)
💡 You can extend this function later to:
Create an
Order
record in your databaseSave line items
Update stock levels
Send a receipt or invoice
4. Add the Webhook URL
In payments/urls.py
, register the new route:
from .views import stripe_webhook
urlpatterns = [
path('create-checkout-session/', CreateCheckoutSessionView.as_view(), name='create_checkout_session'),
path('success/', success_view, name='success'),
path('cancel/', cancel_view, name='cancel'),
path('webhook/', stripe_webhook, name='stripe_webhook'),
]
5. Get Your Webhook Signing Secret
-
In your terminal, run:
stripe listen --forward-to localhost:8000/payments/webhook/
-
This command will output something like:
Ready! Your webhook signing secret is whsec_12345abcde
-
Now Stripe will forward events from your account to your local Django app.
-
Copy that secret and replace it in your code:
endpoint_secret = 'whsec_12345abcde'
Now Stripe will forward events from your account to your local Django app.
6. Test Webhook Events
You can manually trigger a webhook event from Stripe CLI:
stripe trigger checkout.session.completed
Your Django console should log something like:
Payment was successful for session: cs_test_...
If you added email sending, check your console or configure the email backend.
7. (Optional) Create an Order Model
To make things more realistic, you can define an Order
model in a new file products/models.py
(below your Product model):
class Order(models.Model):
session_id = models.CharField(max_length=255)
amount_total = models.DecimalField(max_digits=10, decimal_places=2)
email = models.EmailField()
created_at = models.DateTimeField(auto_now_add=True)
paid = models.BooleanField(default=False)
def __str__(self):
return f"Order {self.id} - {self.email}"
Then in handle_successful_payment(session)
:
from store.models import Order
def handle_successful_payment(session):
Order.objects.create(
session_id=session['id'],
amount_total=session['amount_total'] / 100,
email=session['customer_details']['email'],
paid=True
)
print(f"✅ Order created for {session['customer_details']['email']}")
8. Verify Payment Flow
-
Start the Django server:
python manage.py runserver
-
Start Stripe listener:
stripe listen --forward-to localhost:8000/payments/webhook/
-
Check out again using Stripe test cards.
-
Watch your Django console — it should log a successful payment and create an
Order
record.
✅ Congratulations!
You’ve now built a complete Django e-commerce payment flow:
-
Products and cart
-
Stripe Checkout integration
-
Webhook-based payment confirmation
-
Optional order storage and email notifications
Section 6: Final Touches and Deployment
(Environment Variables, HTTPS, and Static Files)
Now that your Django + Stripe e-commerce app works locally, it’s time to prepare it for real-world deployment with best practices for security and performance.
1. Move Sensitive Data to Environment Variables
You should never hardcode your secret keys (like STRIPE_SECRET_KEY
, DJANGO_SECRET_KEY
, etc.) in settings.py
.
Step 1: Install python-dotenv
pip install python-dotenv
Step 2: Create a .env
file at the root of your project
SECRET_KEY=django-insecure-your-secret-key
DEBUG=False
STRIPE_PUBLIC_KEY=pk_live_xxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx
ALLOWED_HOSTS=yourdomain.com
💡 Never commit
.env
files to Git. Add it to.gitignore
.
Step 3: Load .env
in settings.py
At the top of settings.py
, import os
and load environment variables:
import os
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = os.getenv('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '').split(',')
STRIPE_PUBLIC_KEY = os.getenv('STRIPE_PUBLIC_KEY')
STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY')
2. Configure Static Files for Production
When deploying, Django doesn’t automatically serve static files (CSS, JS, images) — you need to collect them into one directory.
Step 1: Update settings.py
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
Step 2: Run collectstatic
python manage.py collectstatic
This gathers all CSS, JS, and images from your apps into staticfiles/
, which your web server (like Nginx or Gunicorn) can serve.
3. Enforce HTTPS and Secure Settings
To protect user data — especially during checkout — HTTPS is mandatory.
In settings.py
, add the following for production:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
If you’re deploying behind a reverse proxy (like Render or Heroku), also add:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
4. Configure Email Settings (Optional but Recommended)
For order confirmations and notifications, configure Django’s email backend:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.getenv('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASS')
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
Then add these to .env
:
[email protected]
EMAIL_PASS=your_app_password
5. Choose a Deployment Platform
You can deploy your Django project to several platforms easily. Here are 3 common options:
✅ Render (recommended for beginners)
-
Push your project to GitHub.
-
Go to https://render.com → “New Web Service”.
-
Connect your repo, set the environment variables from
.env
. -
Use:
Build Command: pip install -r requirements.txt && python manage.py collectstatic --noinput Start Command: gunicorn django_stripe_ecommerce.wsgi
-
Render automatically provides HTTPS and a free PostgreSQL instance if needed.
✅ Railway
Similar to Render, but faster to set up with one-click deploy from GitHub.
✅ Vercel / Fly.io / AWS
For advanced users needing more control or multi-service setups.
6. Test the Live Stripe Integration
Before going live:
-
Set Stripe API keys to Live mode in your dashboard.
-
Update your
.env
with the live keys. -
Update your webhook endpoint in Stripe to point to your deployed URL:
https://yourdomain.com/payments/webhook/
-
Test again with a real card (or use test mode for dry runs).
7. Final Project Checklist ✅
Task | Status |
---|---|
Django project structured with apps (store , cart , payments ) |
✅ |
Stripe Checkout is integrated and functional | ✅ |
Webhooks verified | ✅ |
Environment variables configured | ✅ |
Static files collected | ✅ |
HTTPS enforced | ✅ |
Deployed with environment-specific settings | ✅ |
Conclusion + Next Steps
Congratulations! 🎉 You’ve just built a fully functional e-commerce website using Django and Stripe Payments — from product listings to checkout and webhook-based payment confirmation. This project demonstrates how Django’s robust backend framework and Stripe’s modern payment APIs work together to create a secure, scalable online store.
Here’s what you accomplished in this tutorial:
-
Set up a modular Django project with separate apps for products, carts, and payments
-
Created a Product model and a dynamic product page
-
Built a session-based shopping cart to store and manage items
-
Integrated Stripe Checkout for real-time, secure card payments
-
Implemented Stripe webhooks to confirm completed orders
-
Prepared your project for production deployment with environment variables, HTTPS, and static file management
This architecture gives you a solid foundation to build a complete e-commerce platform — and Django’s flexibility makes it easy to extend further.
🚀 Next Steps & Enhancements
Now that your store is working, you can make it even better by adding:
-
User Authentication & Profiles
Let users register, log in, and view their order history. Use Django’s built-inUser
model or extend it for more features. -
Order History & Admin Dashboard
Create admin views or customer dashboards to display past purchases, invoices, and order details. -
Product Categories & Search
Add filtering by category or implement full-text search with PostgreSQL or Django Haystack. -
Discount Codes & Coupons
Offer promotional discounts using coupon models tied to order totals. -
Inventory Management
Track stock levels, automatically reduce inventory after successful payments, and display “Out of Stock” notices. -
Email Receipts & Notifications
Use Django’s email backend or a service like SendGrid to send branded order confirmation emails. -
Cloud Deployment
Deploy to production using Render, Railway, or AWS for real-world scalability.
💬 Final Thoughts
This tutorial covered everything you need to get started with Django and Stripe integration — and it’s just the beginning. The skills you’ve learned here apply to countless real-world scenarios, from SaaS billing to subscription systems and digital product stores.
Keep experimenting, refining, and building — your next project could be the next great e-commerce platform!
You can find the full source code on our GitHub.
That's just the basics. If you need more deep learning about Python, Django, FastAPI, Flask, and related, you can take the following cheap course:
- 100 Days of Code: The Complete Python Pro Bootcamp
- Python Mega Course: Build 20 Real-World Apps and AI Agents
- Python for Data Science and Machine Learning Bootcamp
- Python for Absolute Beginners
- Complete Python With DSA Bootcamp + LEETCODE Exercises
- Python Django - The Practical Guide
- Django Masterclass : Build 9 Real World Django Projects
- Full Stack Web Development with Django 5, TailwindCSS, HTMX
- Django - The Complete Course 2025 (Beginner + Advance + AI)
- Ultimate Guide to FastAPI and Backend Development
- Complete FastAPI masterclass from scratch
- Mastering REST APIs with FastAPI
- REST APIs with Flask and Python in 2025
- Python and Flask Bootcamp: Create Websites using Flask!
- The Ultimate Flask Course
Thanks!