$ cat /posts/project-e-commerce-store-with-django-and-payment-integration.md

Project: E-Commerce Store with Django and Payment Integration

drwxr-xr-x2026-01-245 min0 views
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.

pythonecommerce_setup.py
# 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-password

Product 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.

pythonproduct_models.py
# 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 products

Shopping 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.

pythonshopping_cart.py
# 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.

pythonorder_management.py
# 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.

pythonstripe_integration.py
# 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>
FeatureTechnologyPurposeBenefit
Product CatalogDjango ModelsStore product dataOrganized inventory
Shopping CartDjango SessionsMaintain cart stateSeamless shopping
Payment ProcessingStripe APISecure transactionsPCI compliance
Order ManagementModels + AdminTrack purchasesFulfillment workflow
Email NotificationsDjango EmailCustomer communicationOrder confirmation
Always use HTTPS for e-commerce sites protecting customer data and payment information. Implement proper inventory management preventing overselling and test payment integration thoroughly using Stripe test mode before production deployment maintaining transaction security throughout purchase workflow.

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
E-commerce platform demonstrates advanced Django features including session-based cart, Stripe payment integration, order management, and email notifications. Build upon this foundation adding features like product recommendations, wishlists, discount codes, and analytics maintaining scalable architecture integrated with REST API.

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.

$ cat /comments/ (0)

new_comment.sh

// Email hidden from public

>_

$ cat /comments/

// No comments found. Be the first!

[session] guest@{codershandbook}[timestamp] 2026

Navigation

Connect

Subscribe

// 2026 {Coders Handbook}. EOF.