Project: E-Commerce Store with Django and Payment Integration

Building complete e-commerce platform demonstrates advanced Django features implementing products catalog, shopping cart, checkout process, payment integration with Stripe, and order management maintaining production-ready architecture for online retail. E-commerce applications require complex functionality including product variations, inventory management, shopping cart sessions, secure payment processing, order tracking, and customer accounts creating sophisticated requirements beyond basic CRUD operations. Traditional tutorials explain isolated concepts without showing complete e-commerce workflow integration while hands-on project demonstrates real-world implementation solving actual business requirements. Without comprehensive e-commerce experience, developers struggle implementing critical features like payment processing, cart management, order workflow, and inventory tracking creating gaps between learning and production deployment. This complete tutorial builds fully-functional online store from scratch including project setup with multiple apps, product models with categories and variations, shopping cart using Django sessions, user authentication and customer profiles, checkout process with address validation, Stripe payment integration for credit card processing, order management system tracking purchases, email confirmations notifying customers, and admin interface managing store operations. Real-world features include product search and filtering, product reviews and ratings, wishlist functionality, discount codes and promotions, inventory tracking preventing overselling, and sales analytics dashboard. Project demonstrates Django 6.0 best practices including models with proper relationships, class-based views maintaining code reusability, custom model managers encapsulating business logic, form validation ensuring data integrity, template inheritance reducing duplication, and security measures protecting customer data and payment information. This comprehensive guide provides complete code building professional e-commerce platform from initial setup through Stripe integration and production deployment teaching practical Django development maintaining code quality throughout development lifecycle.
E-Commerce Project Setup
Project setup creates Django environment installing dependencies including Stripe SDK, Pillow for images, and configuring multiple apps for products, cart, orders, and payments. Understanding project organization integrated with Django project structure enables maintaining clean separation of concerns throughout development.
# Django 6.0 E-Commerce Project Setup
# Create virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install dependencies
pip install Django==6.0
pip install Pillow # Image handling
pip install stripe # Payment processing
pip install django-crispy-forms crispy-bootstrap5 # Form styling
pip install python-decouple # Environment variables
# Create project
django-admin startproject ecommerce_project
cd ecommerce_project
# Create apps
python manage.py startapp products
python manage.py startapp cart
python manage.py startapp orders
python manage.py startapp payments
python manage.py startapp accounts
# Project structure:
# ecommerce_project/
# βββ manage.py
# βββ ecommerce_project/
# β βββ settings.py
# β βββ urls.py
# β βββ wsgi.py
# βββ products/ # Product catalog
# βββ cart/ # Shopping cart
# βββ orders/ # Order management
# βββ payments/ # Payment processing
# βββ accounts/ # Customer accounts
# Configure settings.py
from decouple import config
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Third-party
'crispy_forms',
'crispy_bootstrap5',
# Local apps
'products',
'cart',
'orders',
'payments',
'accounts',
]
# Stripe configuration
STRIPE_PUBLISHABLE_KEY = config('STRIPE_PUBLISHABLE_KEY')
STRIPE_SECRET_KEY = config('STRIPE_SECRET_KEY')
# Media files
import os
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Session configuration for cart
SESSION_COOKIE_AGE = 86400 # 1 day
# Email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = config('EMAIL_HOST')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
# Create .env file
# .env
STRIPE_PUBLISHABLE_KEY=pk_test_xxxxx
STRIPE_SECRET_KEY=sk_test_xxxxx
EMAIL_HOST=smtp.gmail.com
[email protected]
EMAIL_HOST_PASSWORD=your-app-passwordProduct Models and Catalog
Product models define catalog structure with Category for organization, Product with pricing and inventory, ProductImage for multiple images, and Review for customer feedback. Understanding e-commerce data modeling integrated with Django relationships enables building robust product catalog maintaining data consistency.
# Product models
# products/models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.text import slugify
from django.core.validators import MinValueValidator, MaxValueValidator
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='categories/', blank=True, null=True)
class Meta:
verbose_name_plural = 'Categories'
ordering = ['name']
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('products:category', kwargs={'slug': self.slug})
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
compare_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
stock = models.IntegerField(validators=[MinValueValidator(0)])
available = models.BooleanField(default=True)
featured = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['slug']),
models.Index(fields=['-created_at']),
]
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse('products:product_detail', kwargs={'slug': self.slug})
@property
def in_stock(self):
return self.stock > 0
@property
def discount_percentage(self):
if self.compare_price and self.compare_price > self.price:
return int(((self.compare_price - self.price) / self.compare_price) * 100)
return 0
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
image = models.ImageField(upload_to='products/')
is_primary = models.BooleanField(default=False)
alt_text = models.CharField(max_length=200, blank=True)
def __str__(self):
return f'Image for {self.product.name}'
class Review(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews')
user = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
comment = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
unique_together = ['product', 'user']
def __str__(self):
return f'Review by {self.user.username} for {self.product.name}'
# Run migrations
python manage.py makemigrations products
python manage.py migrate productsShopping Cart Implementation
Shopping cart stores items in Django sessions maintaining cart state across requests without database overhead. Cart class provides methods for adding, removing, and updating items with quantity validation. Understanding session-based cart enables building responsive shopping experience maintaining cart persistence.
# Shopping cart
# cart/cart.py
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(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
def add(self, product, quantity=1, update_quantity=False):
product_id = str(product.id)
if product_id not in self.cart:
self.cart[product_id] = {
'quantity': 0,
'price': str(product.price)
}
if update_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def remove(self, product):
product_id = str(product.id)
if product_id in self.cart:
del self.cart[product_id]
self.save()
def save(self):
self.session.modified = True
def __iter__(self):
product_ids = self.cart.keys()
products = Product.objects.filter(id__in=product_ids)
cart = self.cart.copy()
for product in products:
cart[str(product.id)]['product'] = product
for item in cart.values():
item['price'] = Decimal(item['price'])
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.save()
# Cart views
# cart/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from products.models import Product
from .cart import Cart
from .forms import CartAddProductForm
def cart_detail(request):
cart = Cart(request)
return render(request, 'cart/cart_detail.html', {'cart': cart})
@require_POST
def cart_add(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(
product=product,
quantity=cd['quantity'],
update_quantity=cd['update']
)
return redirect('cart:cart_detail')
@require_POST
def cart_remove(request, product_id):
cart = Cart(request)
product = get_object_or_404(Product, id=product_id)
cart.remove(product)
return redirect('cart:cart_detail')
# Cart form
# cart/forms.py
from django import forms
class CartAddProductForm(forms.Form):
quantity = forms.IntegerField(
min_value=1,
max_value=20,
initial=1
)
update = forms.BooleanField(
required=False,
initial=False,
widget=forms.HiddenInput
)
# Settings addition
# settings.py
CART_SESSION_ID = 'cart'Checkout and Order Management
Order models track purchases with Order storing customer information and OrderItem linking products to orders with quantities and prices. Checkout process validates cart, creates order, and initiates payment maintaining transaction integrity throughout purchase workflow.
# Order models
# orders/models.py
from django.db import models
from django.contrib.auth.models import User
from products.models import Product
class Order(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('processing', 'Processing'),
('shipped', 'Shipped'),
('delivered', 'Delivered'),
('cancelled', 'Cancelled'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='orders')
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
phone = models.CharField(max_length=20)
address = models.CharField(max_length=250)
city = models.CharField(max_length=100)
postal_code = models.CharField(max_length=20)
country = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
stripe_payment_intent = models.CharField(max_length=200, blank=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return f'Order {self.id}'
def get_total_cost(self):
return sum(item.get_cost() for item in self.items.all())
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
product = models.ForeignKey(Product, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField(default=1)
def __str__(self):
return f'{self.quantity}x {self.product.name}'
def get_cost(self):
return self.price * self.quantity
# Order creation view
# orders/views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import Order, OrderItem
from .forms import OrderCreateForm
from cart.cart import Cart
@login_required
def order_create(request):
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.user = request.user
order.save()
# Create order items
for item in cart:
OrderItem.objects.create(
order=order,
product=item['product'],
price=item['price'],
quantity=item['quantity']
)
# Clear cart
cart.clear()
# Redirect to payment
request.session['order_id'] = order.id
return redirect('payments:process')
else:
form = OrderCreateForm()
return render(request, 'orders/create.html', {
'cart': cart,
'form': form
})
# Order form
# orders/forms.py
from django import forms
from .models import Order
class OrderCreateForm(forms.ModelForm):
class Meta:
model = Order
fields = ['first_name', 'last_name', 'email', 'phone',
'address', 'city', 'postal_code', 'country']Stripe Payment Integration
Stripe integration processes credit card payments securely using Payment Intents API with client-side card element collecting payment details and server-side confirmation completing transaction. Understanding payment processing maintains PCI compliance avoiding storing sensitive card data.
# Stripe payment integration
# payments/views.py
import stripe
from django.conf import settings
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse, HttpResponse
from orders.models import Order
stripe.api_key = settings.STRIPE_SECRET_KEY
@login_required
def payment_process(request):
order_id = request.session.get('order_id')
order = get_object_or_404(Order, id=order_id)
if request.method == 'POST':
# Create Stripe Payment Intent
try:
intent = stripe.PaymentIntent.create(
amount=int(order.get_total_cost() * 100), # Convert to cents
currency='usd',
metadata={'order_id': order.id}
)
order.stripe_payment_intent = intent.id
order.save()
return JsonResponse({
'clientSecret': intent.client_secret
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
return render(request, 'payments/process.html', {
'order': order,
'stripe_publishable_key': settings.STRIPE_PUBLISHABLE_KEY
})
@login_required
def payment_completed(request):
order_id = request.session.get('order_id')
order = get_object_or_404(Order, id=order_id)
# Mark order as paid
order.paid = True
order.status = 'processing'
order.save()
# Send confirmation email
from django.core.mail import send_mail
send_mail(
subject=f'Order Confirmation - Order #{order.id}',
message=f'Thank you for your order. Your order #{order.id} has been received.',
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[order.email]
)
return render(request, 'payments/completed.html', {'order': order})
@csrf_exempt
def stripe_webhook(request):
payload = request.body
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
webhook_secret = settings.STRIPE_WEBHOOK_SECRET
try:
event = stripe.Webhook.construct_event(
payload, sig_header, webhook_secret
)
except ValueError:
return HttpResponse(status=400)
except stripe.error.SignatureVerificationError:
return HttpResponse(status=400)
# Handle payment intent succeeded
if event['type'] == 'payment_intent.succeeded':
payment_intent = event['data']['object']
order_id = payment_intent['metadata']['order_id']
order = Order.objects.get(id=order_id)
order.paid = True
order.save()
return HttpResponse(status=200)
# Payment template
# payments/templates/payments/process.html
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('{{ stripe_publishable_key }}');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
const form = document.getElementById('payment-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
// Get client secret from server
const response = await fetch('{% url "payments:process" %}', {
method: 'POST',
headers: {
'X-CSRFToken': '{{ csrf_token }}'
}
});
const data = await response.json();
// Confirm payment
const {error, paymentIntent} = await stripe.confirmCardPayment(
data.clientSecret,
{
payment_method: {
card: cardElement
}
}
);
if (error) {
alert(error.message);
} else {
window.location.href = '{% url "payments:completed" %}';
}
});
</script>| Feature | Technology | Purpose | Benefit |
|---|---|---|---|
| Product Catalog | Django Models | Store product data | Organized inventory |
| Shopping Cart | Django Sessions | Maintain cart state | Seamless shopping |
| Payment Processing | Stripe API | Secure transactions | PCI compliance |
| Order Management | Models + Admin | Track purchases | Fulfillment workflow |
| Email Notifications | Django Email | Customer communication | Order confirmation |
E-Commerce Development Best Practices
- Use HTTPS everywhere: Enforce SSL/TLS for all pages protecting customer data maintaining security
- Implement inventory tracking: Update stock on orders preventing overselling maintaining accurate availability
- Validate payment amounts: Verify cart total matches payment amount preventing price manipulation
- Send order confirmations: Email customers immediately after purchase providing order details
- Handle payment failures: Implement retry logic and error messaging guiding customers through resolution
- Implement refund workflow: Create admin interface handling refunds through Stripe API maintaining records
- Add product reviews: Enable customer reviews building trust and providing social proof
- Optimize images: Compress product images improving page load times maintaining visual quality
- Implement search: Add product search and filtering helping customers find products quickly
- Track analytics: Monitor sales, conversion rates, and cart abandonment optimizing store performance
Conclusion
Building complete e-commerce platform demonstrates advanced Django features implementing product catalog, shopping cart, checkout workflow, payment processing, and order management maintaining production-ready architecture for online retail operations. Project setup establishes foundation installing Django 6.0 with Stripe SDK, Pillow for images, creating separate apps for products, cart, orders, payments, and accounts organizing code maintaining separation of concerns throughout development. Product models define Category organizing products, Product storing pricing and inventory, ProductImage handling multiple images, and Review enabling customer feedback with foreign key relationships maintaining referential integrity through proper delete behaviors. Shopping cart implementation uses Django sessions storing cart items maintaining state across requests without database overhead with Cart class providing add, remove, update, and clear methods encapsulating cart logic maintaining clean interface. Checkout process validates cart contents, creates Order with customer information, generates OrderItem records linking products with quantities and prices, and initiates payment workflow maintaining transaction integrity throughout purchase. Stripe payment integration uses Payment Intents API creating payment on server generating client secret, collecting card details through Stripe Elements maintaining PCI compliance avoiding storing sensitive data, and confirming payment with webhook handling asynchronous payment events. Order management tracks purchase status with pending, processing, shipped, delivered, and cancelled states, sends email confirmations notifying customers, and provides admin interface managing fulfillment workflow. Best practices include using HTTPS everywhere protecting customer data, implementing inventory tracking preventing overselling, validating payment amounts preventing manipulation, sending order confirmations providing purchase details, handling payment failures gracefully, implementing refund workflow through Stripe API, adding product reviews building trust, optimizing images improving performance, implementing search helping discovery, and tracking analytics monitoring business metrics. Understanding complete e-commerce development from product catalog through payment integration integrated with Django sessions, forms, admin interface, and email notifications provides practical foundation building production-ready online stores serving real customers processing transactions maintaining security and reliability throughout application lifecycle.
$ share --platform
$ cat /comments/ (0)
$ cat /comments/
// No comments found. Be the first!


