Ecommerce Website using Django (original) (raw)

Build an e-commerce website using Django that enables users to browse products, manage a shopping cart and place orders through an online system.

ER Diagram of Website

**Customer Interface

  1. Customer shops for a product
  2. Customer changes quantity
  3. The customer adds an item to the cart
  4. Customer views cart
  5. Customer checks out
  6. Customer sends order

2-

ER-diagram for Customer

1-

Use-Case diagram for Customer

**Admin Interface

  1. Admin logs in
  2. Admin inserts item
  3. Admin removes item
  4. Admin modifies item

4

ER-diagram for Admin

3

Use-Case diagram for Admin

Step by Step Implementation

**1. Create Project: Create a new project in your IDE by selecting File -> New Project.

**2. Install Django: Now, install Django using the below command in the terminal

python -m pip install django

**3. Verify Installation: To verify, check the installed Django version using below command

python -m django --version

**4. Create Django Project: Now, to create a new Django project use below command

django-admin startproject project_name

**5. Run Development Server: To run and start the Django server enter following command in the terminal

python manage.py runserver

The application will be available at http://127.0.0.1:8000/. Open this URL in a browser to view the output.

djangorun

Output

Project Directory

project-structure

Project Structure

Project Configuration

Now add store app in E-commerce website in settings.py.

Python `

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'store', ]

`

**ecommerce/urls.py: This file contains all the URL patterns used by the website

Python `

from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static

urlpatterns = [ path('admin/', admin.site.urls), path('', include('store.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

`

Models

**models.py: The below screenshot shows the required models that we will need to create. These models are tables that will be stored in the SQLite database.

django-admin

Django-admin interface

Let's see each model and the fields required by each model.

**category.py: This model defines product categories with a name field, includes a method to retrieve all categories from the database and returns the category name as its string representation.

Python `

from django.db import models

class Category(models.Model): name = models.CharField(max_length=50)

@staticmethod
def get_all_categories():
    return Category.objects.all()

def __str__(self):
    return self.name

`

category

Snapshot of Django-Admin Add category

**customer.py: model for a "Customer" with fields for name, phone, email and password. It includes methods to register, retrieve customers by email and check if a customer exists.

Python `

from django.db import models from django.contrib.auth.hashers import make_password

class Customer(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) phone = models.CharField(max_length=10) email = models.EmailField(unique=True) password = models.CharField(max_length=100)

# Save customer
def register(self):
    # If you want hashed password:
    # self.password = make_password(self.password)
    self.save()

@staticmethod
def get_customer_by_email(email):
    try:
        return Customer.objects.get(email=email)
    except Customer.DoesNotExist:
        return False

def isExists(self):
    return Customer.objects.filter(email=self.email).exists()

class Meta:
    verbose_name_plural = "Customers"

`

customer

Snapshot of Django-Admin Add customers

**products.py: model for "Products" with fields for name, price, category, description and image. It also includes static methods to retrieve products by ID, retrieve all products and retrieve products by category ID.

Python `

from django.db import models from .category import Category

class Products(models.Model): name = models.CharField(max_length=60) price = models.IntegerField(default=0) category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1) description = models.CharField( max_length=250, default='', blank=True, null=True) image = models.ImageField(upload_to='uploads/products/')

@staticmethod
def get_products_by_id(ids):
    return Products.objects.filter(id__in=ids)

@staticmethod
def get_all_products():
    return Products.objects.all()

@staticmethod
def get_all_products_by_categoryid(category_id):
    if category_id:
        return Products.objects.filter(category=category_id)
    else:
        return Products.get_all_products()

`

products

Snapshot of Django-Admin Add products

**orders.py: model for "Order" with fields for product, customer, quantity, price, address, phone, date and status. It also includes methods to place an order and get orders by customer ID.

Python `

from django.db import models from .products import Products from .customer import Customer import datetime

class Order(models.Model): product = models.ForeignKey(Products, on_delete=models.CASCADE) customer = models.ForeignKey(Customer, on_delete=models.CASCADE) quantity = models.IntegerField(default=1) price = models.IntegerField() address = models.CharField(max_length=50, default='', blank=True) phone = models.CharField(max_length=50, default='', blank=True) date = models.DateField(default=datetime.date.today) status = models.BooleanField(default=False)

def placeOrder(self):
    self.save()

@staticmethod
def get_orders_by_customer(customer_id):
    return Order.objects.filter(customer=customer_id).order_by('-date')

class Meta:
    verbose_name_plural = "Orders"

`

orders

Snapshot of Django-Admin Add orders

Views

**views.py: In views, we create a view named home.py, login.py, signup.py, cart.py, checkout.py, orders.py which takes a request and renders an HTML as a response.

In store/views/home.py:

Python `

from django.shortcuts import render, redirect, HttpResponseRedirect from store.models.products import Products from store.models.category import Category from django.views import View

class Index(View): def post(self, request): product = request.POST.get('product') remove = request.POST.get('remove')

    # ensure cart exists and keys are normalized to strings
    cart = request.session.get('cart', {})

    if product:
        pid = str(product)
        quantity = cart.get(pid, 0)

        if remove:
            # remove one or delete
            if quantity <= 1:
                cart.pop(pid, None)
            else:
                cart[pid] = quantity - 1
        else:
            # add/increment
            cart[pid] = quantity + 1

        # save back to session
        request.session['cart'] = cart

    # always redirect after POST (PRG pattern)
    return redirect('homepage')

def get(self, request):
    # list products and categories (same as before)
    products = None
    categories = Category.get_all_categories()
    categoryID = request.GET.get('category')

    if categoryID:
        products = Products.get_all_products_by_categoryid(categoryID)
    else:
        products = Products.get_all_products()

    data = {
        'products': products,
        'categories': categories
    }
    return render(request, 'index.html', data)

def store(request): return render(request, 'store.html')

`

In store/views/login.py:

Python `

from django.shortcuts import render, redirect, HttpResponseRedirect from django.views import View from store.models.customer import Customer from django.contrib.auth.hashers import check_password

class Login(View): return_url = None

def get(self, request):
    Login.return_url = request.GET.get('return_url')
    return render(request, 'login.html')

def post(self, request):
    email = request.POST.get('email')
    password = request.POST.get('password')
    customer = Customer.get_customer_by_email(email)
    error_message = None
    if customer:
        flag = check_password(password, customer.password)
        if flag:
            request.session['customer'] = customer.id
            if Login.return_url:
                return HttpResponseRedirect(Login.return_url)
            else:
                Login.return_url = None
                return redirect('homepage')
        else:
            error_message = 'Email or Password invalid !!'
    else:
        error_message = 'Email or Password invalid !!'
    return render(request, 'login.html', {'error': error_message})

def logout(request): request.session.clear() return redirect('login')

`

HTML Templates

Create an home.html, login.html, signup.html, cart.html, checkout.html, orders.html in the templates. And map the views to store/urls.py:

Python `

from django.urls import path from .views.home import Index, store from .views.signup import Signup from .views.login import Login, logout from .views.cart import Cart from .views.checkout import CheckOut from .views.orders import OrderView from .middlewares.auth import auth_middleware

urlpatterns = [ path('', Index.as_view(), name='homepage'), path('store/', store, name='store'), path('signup/', Signup.as_view(), name='signup'), path('login/', Login.as_view(), name='login'), path('logout/', logout, name='logout'), path('cart/', auth_middleware(Cart.as_view()), name='cart'), path('check-out/', CheckOut.as_view(), name='checkout'), path('orders/', auth_middleware(OrderView.as_view()), name='orders'), ]

`

The below files show the views for each functionality of the site.

**home.py: view for handling an online store. It includes methods for displaying the store's index, adding or removing items from the cart and rendering the store's product listings. The view also uses Django sessions to manage the user's shopping cart.

Python `

from django.shortcuts import render, redirect, HttpResponseRedirect from store.models.products import Products from store.models.category import Category from django.views import View

Create your views here.

class Index(View):

def post(self, request):
    product = request.POST.get('product')
    remove = request.POST.get('remove')
    cart = request.session.get('cart')
    if cart:
        quantity = cart.get(product)
        if quantity:
            if remove:
                if quantity <= 1:
                    cart.pop(product)
                else:
                    cart[product] = quantity-1
            else:
                cart[product] = quantity+1

        else:
            cart[product] = 1
    else:
        cart = {}
        cart[product] = 1

    request.session['cart'] = cart
    print('cart', request.session['cart'])
    return redirect('homepage')

def get(self, request):
    # print()
    return HttpResponseRedirect(f'/store{request.get_full_path()[1:]}')

def store(request): cart = request.session.get('cart') if not cart: request.session['cart'] = {} products = None categories = Category.get_all_categories() categoryID = request.GET.get('category') if categoryID: products = Products.get_all_products_by_categoryid(categoryID) else: products = Products.get_all_products()

data = {}
data['products'] = products
data['categories'] = categories

print('you are : ', request.session.get('email'))
return render(request, 'index.html', data)

`

**login.py: This view handles user authentication, including login and logout. It verifies user credentials, stores the customer ID in the session upon successful login, supports redirection using a return URL and provides a logout function that clears the session and redirects the user to the login page.

Python `

from django.shortcuts import render, redirect, HttpResponseRedirect from django.contrib.auth.hashers import check_password from store.models.customer import Customer from django.views import View

class Login(View): return_url = None

def get(self, request):
    Login.return_url = request.GET.get('return_url')
    return render(request, 'login.html')

def post(self, request):
    email = request.POST.get('email')
    password = request.POST.get('password')
    customer = Customer.get_customer_by_email(email)
    error_message = None
    if customer:
        flag = check_password(password, customer.password)
        if flag:
            request.session['customer'] = customer.id

            if Login.return_url:
                return HttpResponseRedirect(Login.return_url)
            else:
                Login.return_url = None
                return redirect('homepage')
        else:
            error_message = 'Invalid !!'
    else:
        error_message = 'Invalid !!'

    print(email, password)
    return render(request, 'login.html', {'error': error_message})

def logout(request): request.session.clear() return redirect('login')

`

**signup.py: This view handles user registration by collecting user details, validating input data, hashing the password for security and saving the user to the database. If validation fails, appropriate error messages are displayed on the sign-up page.

Python `

from django.shortcuts import render, redirect from django.contrib.auth.hashers import make_password from store.models.customer import Customer from django.views import View

class Signup (View): def get(self, request): return render(request, 'signup.html')

def post(self, request):
    postData = request.POST
    first_name = postData.get('firstname')
    last_name = postData.get('lastname')
    phone = postData.get('phone')
    email = postData.get('email')
    password = postData.get('password')
    # validation
    value = {
        'first_name': first_name,
        'last_name': last_name,
        'phone': phone,
        'email': email
    }
    error_message = None

    customer = Customer(first_name=first_name,
                        last_name=last_name,
                        phone=phone,
                        email=email,
                        password=password)
    error_message = self.validateCustomer(customer)

    if not error_message:
        print(first_name, last_name, phone, email, password)
        customer.password = make_password(customer.password)
        customer.register()
        return redirect('homepage')
    else:
        data = {
            'error': error_message,
            'values': value
        }
        return render(request, 'signup.html', data)

def validateCustomer(self, customer):
    error_message = None
    if (not customer.first_name):
        error_message = "Please Enter your First Name !!"
    elif len(customer.first_name) < 3:
        error_message = 'First Name must be 3 char long or more'
    elif not customer.last_name:
        error_message = 'Please Enter your Last Name'
    elif len(customer.last_name) < 3:
        error_message = 'Last Name must be 3 char long or more'
    elif not customer.phone:
        error_message = 'Enter your Phone Number'
    elif len(customer.phone) < 10:
        error_message = 'Phone Number must be 10 char Long'
    elif len(customer.password) < 5:
        error_message = 'Password must be 5 char long'
    elif len(customer.email) < 5:
        error_message = 'Email must be 5 char long'
    elif customer.isExists():
        error_message = 'Email Address Already Registered..'
    # saving

    return error_message

`

**cart.py: This model represents an order in the e-commerce system. It stores product and customer references along with quantity, price, delivery details, date and status. It also provides methods to place an order and retrieve customer-specific orders sorted by date.

Python `

from django.db import models from .product import Products from .customer import Customer import datetime

class Order(models.Model): product = models.ForeignKey(Products, on_delete=models.CASCADE) customer = models.ForeignKey(Customer, on_delete=models.CASCADE) quantity = models.IntegerField(default=1) price = models.IntegerField() address = models.CharField(max_length=50, default='', blank=True) phone = models.CharField(max_length=50, default='', blank=True) date = models.DateField(default=datetime.datetime.today) status = models.BooleanField(default=False)

def placeOrder(self):
    self.save()

@staticmethod
def get_orders_by_customer(customer_id):
    return Order.objects.filter(customer=customer_id).order_by('-date')

`

**checkout.py: This view handles the checkout process by collecting the customer’s address and phone number via a POST request, retrieving cart and user details from the session, creating order records for selected products, clearing the cart, and redirecting the user to the cart page.

Python `

from django.shortcuts import render, redirect from django.contrib.auth.hashers import check_password from store.models.customer import Customer from django.views import View from store.models.products import Products from store.models.orders import Order

class CheckOut(View): def post(self, request): address = request.POST.get('address') phone = request.POST.get('phone') customer = request.session.get('customer') cart = request.session.get('cart') products = Products.get_products_by_id(list(cart.keys())) print(address, phone, customer, cart, products)

    for product in products:
        print(cart.get(str(product.id)))
        order = Order(customer=Customer(id=customer),
                      product=product,
                      price=product.price,
                      address=address,
                      phone=phone,
                      quantity=cart.get(str(product.id)))
        order.save()
    request.session['cart'] = {}

    return redirect('cart')

`

**orders.py: This view displays order history for authenticated users. It retrieves the customer ID from the session, fetches their orders from the database and renders them in the orders.html template. Access is restricted using auth_middleware.

Python `

from django.shortcuts import render, redirect from django.contrib.auth.hashers import check_password from store.models.customer import Customer from django.views import View from store.models.products import Products from store.models.orders import Order from store.middlewares.auth import auth_middleware

class OrderView(View):

def get(self, request):
    customer = request.session.get('customer')
    orders = Order.get_orders_by_customer(customer)
    print(orders)
    return render(request, 'orders.html', {'orders': orders})

`