Python Django Complete E-Commerce Project With Bootstrap 5 in Tamil


CategoryWed Designing
LanguagePython Django
Author Tutor Joes

The purpose of this article is to demonstrate to learn how to create complete E-Commerce site using Python Django and MySQL.

What is Django?

Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

Features

  • Ridiculously fast
  • Reassuringly secure
  • Exceedingly scalable

Source Code


Template Files

static/css/style.css
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@300;400;500;700&display=swap');

html {
  font-size: 14px;
}
body {
  font-family: 'Noto Sans', sans-serif;
}
a {
  text-decoration: none;
}

.carousel-item img {
  object-fit: cover;
  object-position: top;
  height: 60vh;
  overflow: hidden;
}

.old_price {
  font-weight: bold;
  color: red;
}

.new_price {
  font-weight: bold;
  background-color: green;
  color: white;
  padding: 2px;
  border-radius: 5px;
  margin-bottom: 2px;
}

.pic-box {
  position: relative;
}

.hot {
  background-color: orangered;
  color: white;
  width: 50px;
  text-align: center;
  font-weight: bold;
  display: inline;
  border-radius: 5px;
  padding: 5px;
  position: absolute;
  top: 0;
  right: 20px;
  z-index: 10;
}

Included files


shop/templates/shop/layouts/main.html
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>
      {% block title %}
      {% endblock title %}
      </title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
      <link rel="stylesheet" href="{% static 'css/style.css' %}">
  </head>
  <body>
    {% include 'shop/inc/navbar.html' %}
    {% block content %}
    {% endblock content %}
    {% block scripts %}
    {% endblock scripts %}
    {% include 'shop/inc/footer.html' %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  </body>
</html>
shop/templates/shop/inc/message.html
{% for msg in messages %}
<div class="alert alert-info alert-dismissible fade show" role="alert">
  {{msg}}
  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
shop/templates/shop/inc/navbar.html
<nav class="navbar navbar-expand-lg  navbar-dark bg-dark fixed-top">
  <div class="container">
    <a class="navbar-brand" href="{% url 'home' %}"><i class="fa fa-cart-plus"></i> ShopKart</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
      <div class="navbar-nav ms-auto">
        <a class="nav-link" aria-current="page" href="{% url 'home' %}"><i class="fa fa-home"></i> Home</a>
        {% if request.user.is_authenticated %}
          <a class="nav-link" aria-current="page" href="#"><i class="fa fa-user"></i> {{request.user}}</a>
          <a class="nav-link" aria-current="page" href="{% url 'logout' %}"><i class="fa fa-sign-out"></i> Logout</a>
        {% else %}
          <a class="nav-link" href="{% url 'login' %}"><i class="fa fa-sign-in"></i> Login</a>
          <a class="nav-link" href="{% url 'register' %}"><i class="fa fa-users"></i> Register</a>
        {% endif %}
          <a class="nav-link" href="{% url 'collections' %}"><i class="fa fa-cubes"></i> Collections</a>
          <a class="nav-link" href="{% url 'cart' %}"><i class="fa fa-shopping-cart"></i> Cart</a>
          <a class="nav-link" href="{% url 'favviewpage' %}"><i class="fa fa-heart"></i> Favourite</a>
      </div>
    </div>
  </div>
</nav>
shop/templates/shop/inc/slider.html
{% load static %}
<div id="carouselExampleIndicators" class="carousel slide" data-bs-ride="carousel">
  <div class="carousel-indicators">
    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1" aria-label="Slide 2"></button>
    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2" aria-label="Slide 3"></button>
    <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="3" aria-label="Slide 4"></button>
  </div>
  <div class="carousel-inner">
    <div class="carousel-item active">
      <img src="{% static 'images/1.jpg' %}" class="d-block w-100" alt="Slide 1">
    </div>
    <div class="carousel-item">
      <img src="{% static 'images/2.jpg' %}" class="d-block w-100" alt="Slide 2">
    </div>
    <div class="carousel-item">
      <img src="{% static 'images/3.jpg' %}" class="d-block w-100" alt="Slide 3">
    </div>
    <div class="carousel-item">
      <img src="{% static 'images/4.jpg' %}" class="d-block w-100" alt="Slide 4">
    </div>
  </div>
  <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Previous</span>
  </button>
  <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Next</span>
  </button>
</div>
shop/templates/shop/inc/footer.html
<footer class="text-center text-lg-start bg-dark text-white">
    <section class="container d-flex justify-content-center justify-content-lg-between p-4">
      <div class="me-5 d-none d-lg-block">
        <span>Get connected with us on social networks:</span>
      </div>
      <div>
        <a href="" class="me-4 text-reset"><i class="fa fa-facebook"></i></a>
        <a href="" class="me-4 text-reset"><i class="fa fa-twitter"></i></a>
        <a href="" class="me-4 text-reset"><i class="fa fa-google"></i></a>
        <a href="" class="me-4 text-reset"><i class="fa fa-instagram"></i></a>
        <a href="" class="me-4 text-reset"><i class="fa fa-linkedin"></i></a>
        <a href="" class="me-4 text-reset"><i class="fa fa-github"></i></a>
      </div>
    </section>
  
    <section class="">
      <div class="container text-center text-md-start mt-5">
        <div class="row mt-3">
          <div class="col-md-3 col-lg-4 col-xl-3 mx-auto mb-4">
            <h6 class="text-uppercase fw-bold mb-4"><i class="fa fa-cart-plus"></i> ShopKart</h6>
            <p>
              shopkart.com is a one stop destination for your family's fashion needs.
               We give you the opportunity to give your wardrobe a makeover with the latest collections from our top brands.
            </p>
          </div>
  
          <div class="col-md-2 col-lg-2 col-xl-2 mx-auto mb-4">
            <h6 class="text-uppercase fw-bold mb-4">Make Money with Us</h6>
            <p><a href="#!" class="text-reset">Sell on ShopKart</a></p>
            <p><a href="#!" class="text-reset">Advertise Your Products</a></p>
            <p><a href="#!" class="text-reset">Become an Affiliate</a></p>
            <p><a href="#!" class="text-reset">Fulfilment by ShopKart</a></p>
          </div>
          <div class="col-md-3 col-lg-2 col-xl-2 mx-auto mb-4">
            <h6 class="text-uppercase fw-bold mb-4">Useful links</h6>
            <p><a href="#!" class="text-reset">FAQ</a></p>
            <p><a href="#!" class="text-reset">Feedback</a></p>
            <p><a href="#!" class="text-reset">About Us</a></p>
            <p><a href="#!" class="text-reset">Contact Us</a></p>
          </div>
          
          <div class="col-md-4 col-lg-3 col-xl-3 mx-auto mb-md-0 mb-4">
            <h6 class="text-uppercase fw-bold mb-4"> Contact</h6>
            <p><i class="fa fa-home"></i> Tutor Joes</p>
            <p><i class="fa fa-envelope"></i> info@example.com</p>
            <p><i class="fa fa-phone"></i> + 91 9043017689</p>
          </div>
  
        </div>
      </div>
    </section>
    <div class="text-center p-4">
      &copy;  2021 Copyright <a class="text-reset fw-bold" href="https://tutorjoes.in/"> tutorjoes.in</a>
    </div>
  </footer>
shop/templates/shop/index.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
ShopKart | Online Shopping
{% endblock title %}

{% block content %}
{% include 'shop/inc/slider.html' %}
  <div class="container" style="margin-top:70px;" >
    <div class="row">
      <div class="col-12">
        <h4 class="mb-3"> Latest Offfers</h4>
        <hr style="border-color:#b8bfc2;">
      </div>
      {% for item in products %}
      <div class="col-md-4 col-lg-3">
        <div class="card my-3">
          <img src="{{item.product_image.url}}"  class="card-image-top" alt="Categories">
          <a href="{% url 'product_details' item.category.name item.name %}">
          <div class="card-body">
            <h5 class="card-title text-primary">{{ item.name }}</h5>
            <p class="card-text">
              <span class="float-start old_price"><s>Rs.{{ item.original_price | stringformat:'d'}}</s></span>
              <span class="float-end new_price">Rs.{{ item.selling_price | stringformat:'d' }}</span>
            </p>
          </div>
        </a>
        </div>
      </div>
      {% endfor %}
    </div>
  </div>
{% endblock content %}

shop/templates/shop/register.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
  Registration | ShopKart
{% endblock title %}
{% block content %}
  <div class="container" style="margin-top:70px;min-height:600px;">
    <div class="row">
      <div class="col-12">
        <h4 class="mb-3"> New User Registration</h4>
        <hr style="border-color:#b8bfc2;">
        {% include 'shop/inc/message.html' %}
      </div>
    </div>
    <section class="py-4" >
      <div class="container">
        <div class="row">
          <div class="col-6">
            <form method="post" action="">
              {% csrf_token %}
              <div class="mb-4">
                <label for="" class="form-label">User Name</label>
                {{form.username}}
              </div>
              <div class="mb-4">
                <label for="" class="form-label">User Email</label>
                {{form.email}}
              </div>
              <div class="mb-4">
                <label for="" class="form-label">Password</label>
                {{form.password1}}
              </div>
              <div class="mb-4">
                <label for="" class="form-label">Confirm Password</label>
                {{form.password2}}
              </div>
              <button type="submit" class="btn btn-primary">Register</button>
            </form>
            <p class="my-2">Already user ? <a href="{% url 'login' %}">Login Now</a> </p>
          </div>
          <div class="col-6">
            
                {% if form.errors.username %}
                  <label class="text-danger d-block">{{ form.errors.username }}</label>
                {% endif %}
            
                {% if form.errors.email %}
                <label class="text-danger d-block">{{ form.errors.email }}</label>
                {% endif %}
              
                {% if form.errors.password1 %}
                <label class="text-danger d-block">{{ form.errors.password1 }}</label>
                {% endif %}
              
                {% if form.errors.password2 %}
                <label class="text-danger d-block">{{ form.errors.password2 }}</label>
                {% endif %}
              
          </div>
        </div>
      </div>
    </section>
  </div>
{% endblock content %}
shop/templates/shop/login.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
  Registration | ShopKart
{% endblock title %}
{% block content %}
  <div class="container" style="margin-top:70px;min-height:600px;">
    <div class="row">
      <div class="col-12">
        <h4 class="mb-3"> User Login</h4>
        <hr style="border-color:#b8bfc2;">
        {% include 'shop/inc/message.html' %}
      </div>
    </div>
    <section class="py-4" >
      <div class="container">
        <div class="row">
          <div class="col-6">
            <form method="post" action="">
              {% csrf_token %}
              <div class="mb-4">
                <label for="" class="form-label">User Name</label>
                <input type="text" name="username" id="username" class="form-control" placeholder="Enter User Name">
              </div>
              <div class="mb-4">
                <label for="" class="form-label">Password</label>
                <input type="password" name="password" id="password" class="form-control" placeholder="Enter Password">
              </div>
              <button type="submit" class="btn btn-primary">Login</button>
            </form>
          </div>
        </div>
      </div>
    </section>
  </div>
{% endblock content %}
shop/templates/shop/collection.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
  Registration | ShopKart
{% endblock title %}
{% block content %}
  <section class="py-5 text-center container"  style="margin-top:70px;">
    <div class="row py-lg-5">
      <div class="col-lg-6 col-md-8 mx-auto">
        <h1 class="fw-light">Bestsellers</h1>
        <p class="lead text-muted">Our most popular products based on sales. Updated hourly.</p>
        <p>
          <a href="{% url 'login' %}" class="btn btn-primary my-2">Already User</a>
          <a href="{% url 'register' %}" class="btn btn-secondary my-2">Register</a>
        </p>
      </div>
    </div>
  </section>
  <section class="bg-light py-4 my-5" style="min-height:600px;">
    <div class="container">
      <div class="row">
        <div class="col-12">
          <h4 class="mb-3">Categories</h4>
          <hr style="border-color:#b8bfc2;">
          {% include 'shop/inc/message.html' %}
        </div>
        {% for item in catagory %}
        <div class="col-md-4 col-lg-3">
          <div class="card my-3">
            <img src="{{item.image.url}}"  class="card-image-top" alt="Categories">
            <a href="{% url 'collections' item.name %}">
            <div class="card-body">
              <h5 class="card-title text-primary">{{ item.name }}</h5>
              <p class="card-text">{{ item.description }}</p>
    
            </div>
          </a>
          </div>
        </div>
        {% endfor %}

      </div>
      </div>
  </section>

{% endblock content %}
shop/templates/shop/fav.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
  Registration | ShopKart
{% endblock title %}
{% block content %}
  <section class="bg-light py-4 my-5" style="min-height:600px;">
    <div class="container">
      <div class="row">
        <div class="col-12">
          <h4 class="mb-3">Favourite Item</h4>
          <hr style="border-color:#b8bfc2;">
        </div>
      
        <table>
            <tr>
                <th>Image</th>
                <th>Product Name</th>
                <th>Unit</th>
                <th>Remove</th>
            </tr>
          

            {% for item in fav %}
           <tr>
              <td><img src="{{item.product.product_image.url}}" height="75px" alt="{{item.product.name}}"></td>
              <td>{{item.product.name}}</td>
              <td>{{item.product.selling_price | stringformat:'d'}}</td>
              <td><a href="{% url 'remove_fav' item.id %}"  onclick="return confirm('Are you sure? to Remove')"  class="btn btn-danger btn-sm"><i class="fa fa-trash"></i> Remove</a></td>
            </tr>
            {% endfor %}
            <tr>
        </table>
       
      </div>
      </div>
  </section>
{% endblock content %}
shop/templates/shop/cart.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
  Registration | ShopKart
{% endblock title %}
{% block content %}
  <section class="bg-light py-4 my-5" style="min-height:600px;">
    <div class="container">
      <div class="row">
        <div class="col-12">
          <h4 class="mb-3">Cart  Items</h4>
          <hr style="border-color:#b8bfc2;">
        </div>
      
        <table>
            <tr>
                <th>Image</th>
                <th>Product Name</th>
                <th>Unit</th>
                <th>Quantity</th>
                <th>Amount</th>
                <th>Remove</th>
            </tr>
          

            {% for item in cart %}
           <tr>
              <td><img src="{{item.product.product_image.url}}" height="75px" alt="{{item.product.name}}"></td>
              <td>{{item.product.name}}</td>
              <td>{{item.product.selling_price | stringformat:'d'}}</td>
              <td>{{item.product_qty}}</td>
              <td class="amt">{{item.total_cost | stringformat:'d'}}</td>
              <td><a href="{% url 'remove_cart' item.id %}"  onclick="return confirm('Are you sure? to Remove')"  class="btn btn-danger btn-sm"><i class="fa fa-trash"></i> Remove</a></td>
            </tr>
            {% endfor %}
            <tr>
              <td></td>
              <td></td>
              <td colspan="2"><b>Total Amount</b></td>
              <th id="net">0</th>
              <td><button class="btn btn-primary btn-sm">
                <i class="fa fa-check-circle"></i> Check Out
              </button></td>
            </tr>
           
        </table>
       
      </div>
      </div>
  </section>

  <script>
    const nodes = document.querySelectorAll('.amt');
    const arr = Array.from(nodes);
    const res = arr.reduce((acc, curr) => {
     return acc += Number(curr.textContent)
    }, 0);
    document.getElementById("net").innerHTML="Rs : "+res;

  </script>
{% endblock content %}
shop/templates/shop/products/index.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
ShopKart | Online Shopping
{% endblock title %}

{% block content %}
<section class="bg-light py-4 my-5" style="min-height:600px;">
  <div class="container">
    <div class="row">
      <div class="col-12">
        <h4 class="mb-3">{{category_name}} Products</h4>
        <hr style="border-color:#b8bfc2;">
        <nav aria-label="breadcrumb">
          <ol class="breadcrumb">
            <li class="breadcrumb-item"><a href="{% url 'home' %}">Home</a></li>
            <li class="breadcrumb-item active">{{category_name}} Collections</li>
          </ol>
        </nav>
        {% include 'shop/inc/message.html' %}
      </div>
      {% for item in products %}
      <div class="col-md-4 col-lg-3">
        <div class="card my-3">
          <img src="{{item.product_image.url}}"  class="card-image-top" alt="Categories">
          <a href="{% url 'product_details' category_name item.name %}">
          <div class="card-body">
            <h5 class="card-title text-primary">{{ item.name }}</h5>
            <p class="card-text">
              <span class="float-start old_price"><s>Rs.{{ item.original_price | stringformat:'d'}}</s></span>
              <span class="float-end new_price">Rs.{{ item.selling_price | stringformat:'d' }}</span>
            </p>
          </div>
        </a>
        </div>
      </div>
      {% endfor %}
    </div>
  </div>
</section>
 
{% endblock content %}

shop/templates/shop/products/product_details.html
{% extends 'shop/layouts/main.html' %}
{% block title %}
ShopKart | Online Shopping
{% endblock title %}

{% block content %}
<section class="bg-light py-4 my-5" style="min-height:600px;">
  <div class="container">
    <div class="row">
      <div class="col-12">
        <h4 class="mb-3">  {{products}} Details</h4>
        <hr style="border-color:#b8bfc2;">
        <nav aria-label="breadcrumb">
          <ol class="breadcrumb">
            <li class="breadcrumb-item"><a href="{% url 'home' %}">Home</a></li>
            <li class="breadcrumb-item"><a href="{% url 'collections' products.category.name  %}">Collections</a></li>
            <li class="breadcrumb-item active" aria-current="page">{{products}}</li>
          </ol>
        </nav>
        {% include 'shop/inc/message.html' %}
      </div>
      <div class="col-4 my-3 pic-box">
        {% if products.trending %}
          <div class="hot">Hot</div>
          {% endif %}
          <img src="{{products.product_image.url}}"  class="card-image-top" alt="{{products}}">
      </div>
      <div class="col-8 my-3">
          <h5 class="text-success">{{products | upper}}</h5>
          <p>{{products.vendor}}</p>
          <p>{{products.description}}</p>
          <h6 class="my-2 text-danger">Current Price : Rs. <s>{{products.original_price}}</s></h6>
          <h5 class="my-2 text-primary">Offer Price   : Rs.{{products.selling_price}}</h5>
          <div class="my-3">
            {% if products.quantity > 0 %}
            <input type="hidden" value="{{products.id}}" id="pid">
            
              <p>
                <div class="input-group" style="width:150px">
                  <button class="input-group-text bg-success text-light" id="btnMinus" ><i class="fa fa-minus"></i></button>
                    <input type="text" name="qty" id="txtQty" value="1" class="form-control text-center">
                  <button class="input-group-text bg-success text-light" id="btnPlus"><i class="fa fa-plus"></i></button>
                </div>
              </p>
             <button class="btn btn-primary" id="btnCart"><i class="fa fa-shopping-cart"></i> Add to Cart</button>
            {% else %}
            <button class="btn btn-secondary"><i class="fa fa-minus"></i> Out of Stock</button>
            {% endif %}
            <button class="btn btn-danger" id="btnFav"><i class="fa fa-heart"></i></button>
          </div>
      </div>
    </div>
  </div>
</section>
 <script>
document.addEventListener("DOMContentLoaded", function(event) {
  const btnPlus = document.getElementById("btnPlus");
  const btnMinus = document.getElementById("btnMinus");
  const txtQty = document.getElementById("txtQty");
  const pid = document.getElementById("pid");
  const btnCart = document.getElementById("btnCart");
  const btnFav = document.getElementById("btnFav");

  btnPlus.addEventListener("click", function() {
    let qty=parseInt(txtQty.value,10);
    qty=isNaN(qty)?0:qty;
    //console.log(qty);
    if(qty<10){
      qty++;
      txtQty.value=qty;
    }
  });

  btnMinus.addEventListener("click", function() {
      let qty=parseInt(txtQty.value,10);
      qty=isNaN(qty)?0:qty;
      //console.log(qty);
      if(qty>1){
        qty--;
        txtQty.value=qty;
      }
  });

  btnCart.addEventListener("click", function() {
      let qty=parseInt(txtQty.value,10);
      qty=isNaN(qty)?0:qty;
      
      if(qty>0){
        let postObj = { 
            'product_qty': qty, 
            'pid': pid.value
        }
        //console.log(postObj);
        fetch("/addtocart",{
          method: 'POST',
          credentials: 'same-origin',
          headers:{
              'Accept': 'application/json',
              'X-Requested-With': 'XMLHttpRequest',
              'X-CSRFToken': '{{ csrf_token }}',
          },
          body: JSON.stringify(postObj)
        }).then(response => {
	        return response.json();
        }).then(data => {
        	//console.log(data);
          alert(data['status']);
        });
 

      }else{
        alert("Please Enter The Quantity");
      }
      
  });


  btnFav.addEventListener("click", function() {
     
        let postObj = { 
            'pid': pid.value
        }
        console.log(postObj);
        fetch("/fav",{
          method: 'POST',
          credentials: 'same-origin',
          headers:{
              'Accept': 'application/json',
              'X-Requested-With': 'XMLHttpRequest',
              'X-CSRFToken': '{{ csrf_token }}',
          },
          body: JSON.stringify(postObj)
        }).then(response => {
	        return response.json();
        }).then(data => {
        	//console.log(data);
          alert(data['status']);
        });
      
  });


});
 </script>
{% endblock content %}

Python Files


shop/admin.py

from atexit import register
from django.contrib import admin
from .models import *
 
 
"""
class CategoryAdmin(admin.ModelAdmin):
  list_display = ('name', 'image', 'description')
admin.site.register(Catagory,CategoryAdmin)
"""
 
admin.site.register(Catagory)
admin.site.register(Product)
admin.site.register(Cart)
admin.site.register(Favourite)
 

shop/apps.py

from django.apps import AppConfig
 
 
class ShopConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'shop'
 

shop/form.py

from pyexpat import model
from django.contrib.auth.forms import UserCreationForm
from .models import User
from django import forms
 
class CustomUserForm(UserCreationForm):
  username=forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Enter User Name'}))
  email=forms.CharField(widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Enter Email Address'}))
  password1=forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Enter Your Password'}))
  password2=forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'Enter Confirm Password'}))
  class Meta:
    model=User
    fields=['username','email','password1','password2']

shop/models.py

from itertools import product
from django.db import models
from django.contrib.auth.models import User
import datetime
import os
 
def getFileName(requset,filename):
  now_time=datetime.datetime.now().strftime("%Y%m%d%H:%M:%S")
  new_filename="%s%s"%(now_time,filename)
  return os.path.join('uploads/',new_filename)
 
class Catagory(models.Model):
  name=models.CharField(max_length=150,null=False,blank=False)
  image=models.ImageField(upload_to=getFileName,null=True,blank=True)
  description=models.TextField(max_length=500,null=False,blank=False)
  status=models.BooleanField(default=False,help_text="0-show,1-Hidden")
  created_at=models.DateTimeField(auto_now_add=True)
 
  def __str__(self) :
    return self.name
 
class Product(models.Model):
  category=models.ForeignKey(Catagory,on_delete=models.CASCADE)
  name=models.CharField(max_length=150,null=False,blank=False)
  vendor=models.CharField(max_length=150,null=False,blank=False)
  product_image=models.ImageField(upload_to=getFileName,null=True,blank=True)
  quantity=models.IntegerField(null=False,blank=False)
  original_price=models.FloatField(null=False,blank=False)
  selling_price=models.FloatField(null=False,blank=False)
  description=models.TextField(max_length=500,null=False,blank=False)
  status=models.BooleanField(default=False,help_text="0-show,1-Hidden")
  trending=models.BooleanField(default=False,help_text="0-default,1-Trending")
  created_at=models.DateTimeField(auto_now_add=True)
 
  def __str__(self) :
    return self.name
 
class Cart(models.Model):
  user=models.ForeignKey(User,on_delete=models.CASCADE)
  product=models.ForeignKey(Product,on_delete=models.CASCADE)
  product_qty=models.IntegerField(null=False,blank=False)
  created_at=models.DateTimeField(auto_now_add=True)
 
  @property
  def total_cost(self):
    return self.product_qty*self.product.selling_price
 
class Favourite(models.Model):
	user=models.ForeignKey(User,on_delete=models.CASCADE)
	product=models.ForeignKey(Product,on_delete=models.CASCADE)
	created_at=models.DateTimeField(auto_now_add=True)
 

shop/urls.py

from django.urls import path
from . import views
 
urlpatterns= [
    path('',views.home,name="home"),
    path('register',views.register,name="register"),
    path('login',views.login_page,name="login"),
    path('logout',views.logout_page,name="logout"),
    path('cart',views.cart_page,name="cart"),
    path('fav',views.fav_page,name="fav"),
    path('favviewpage',views.favviewpage,name="favviewpage"),
    path('remove_fav/<str:fid>',views.remove_fav,name="remove_fav"),
    path('remove_cart/<str:cid>',views.remove_cart,name="remove_cart"),
    path('collections',views.collections,name="collections"),
    path('collections/<str:name>',views.collectionsview,name="collections"),
    path('collections/<str:cname>/<str:pname>',views.product_details,name="product_details"),
    path('addtocart',views.add_to_cart,name="addtocart"),
]
 

shop/views.py

from django.http import  JsonResponse
from django.shortcuts import redirect, render
from shop.form import CustomUserForm
from . models import *
from django.contrib import messages
from django.contrib.auth import authenticate,login,logout
import json
 
 
def home(request):
  products=Product.objects.filter(trending=1)
  return render(request,"shop/index.html",{"products":products})
 
def favviewpage(request):
  if request.user.is_authenticated:
    fav=Favourite.objects.filter(user=request.user)
    return render(request,"shop/fav.html",{"fav":fav})
  else:
    return redirect("/")
 
def remove_fav(request,fid):
  item=Favourite.objects.get(id=fid)
  item.delete()
  return redirect("/favviewpage")
 
 
 
 
def cart_page(request):
  if request.user.is_authenticated:
    cart=Cart.objects.filter(user=request.user)
    return render(request,"shop/cart.html",{"cart":cart})
  else:
    return redirect("/")
 
def remove_cart(request,cid):
  cartitem=Cart.objects.get(id=cid)
  cartitem.delete()
  return redirect("/cart")
 
 
 
def fav_page(request):
   if request.headers.get('x-requested-with')=='XMLHttpRequest':
    if request.user.is_authenticated:
      data=json.load(request)
      product_id=data['pid']
      product_status=Product.objects.get(id=product_id)
      if product_status:
         if Favourite.objects.filter(user=request.user.id,product_id=product_id):
          return JsonResponse({'status':'Product Already in Favourite'}, status=200)
         else:
          Favourite.objects.create(user=request.user,product_id=product_id)
          return JsonResponse({'status':'Product Added to Favourite'}, status=200)
    else:
      return JsonResponse({'status':'Login to Add Favourite'}, status=200)
   else:
    return JsonResponse({'status':'Invalid Access'}, status=200)
 
 
def add_to_cart(request):
   if request.headers.get('x-requested-with')=='XMLHttpRequest':
    if request.user.is_authenticated:
      data=json.load(request)
      product_qty=data['product_qty']
      product_id=data['pid']
      #print(request.user.id)
      product_status=Product.objects.get(id=product_id)
      if product_status:
        if Cart.objects.filter(user=request.user.id,product_id=product_id):
          return JsonResponse({'status':'Product Already in Cart'}, status=200)
        else:
          if product_status.quantity>=product_qty:
            Cart.objects.create(user=request.user,product_id=product_id,product_qty=product_qty)
            return JsonResponse({'status':'Product Added to Cart'}, status=200)
          else:
            return JsonResponse({'status':'Product Stock Not Available'}, status=200)
    else:
      return JsonResponse({'status':'Login to Add Cart'}, status=200)
   else:
    return JsonResponse({'status':'Invalid Access'}, status=200)
 
def logout_page(request):
  if request.user.is_authenticated:
    logout(request)
    messages.success(request,"Logged out Successfully")
  return redirect("/")
 
 
def login_page(request):
  if request.user.is_authenticated:
    return redirect("/")
  else:
    if request.method=='POST':
      name=request.POST.get('username')
      pwd=request.POST.get('password')
      user=authenticate(request,username=name,password=pwd)
      if user is not None:
        login(request,user)
        messages.success(request,"Logged in Successfully")
        return redirect("/")
      else:
        messages.error(request,"Invalid User Name or Password")
        return redirect("/login")
    return render(request,"shop/login.html")
 
def register(request):
  form=CustomUserForm()
  if request.method=='POST':
    form=CustomUserForm(request.POST)
    if form.is_valid():
      form.save()
      messages.success(request,"Registration Success You can Login Now..!")
      return redirect('/login')
  return render(request,"shop/register.html",{'form':form})
 
 
def collections(request):
  catagory=Catagory.objects.filter(status=0)
  return render(request,"shop/collections.html",{"catagory":catagory})
 
def collectionsview(request,name):
  if(Catagory.objects.filter(name=name,status=0)):
      products=Product.objects.filter(category__name=name)
      return render(request,"shop/products/index.html",{"products":products,"category_name":name})
  else:
    messages.warning(request,"No Such Catagory Found")
    return redirect('collections')
 
 
def product_details(request,cname,pname):
    if(Catagory.objects.filter(name=cname,status=0)):
      if(Product.objects.filter(name=pname,status=0)):
        products=Product.objects.filter(name=pname,status=0).first()
        return render(request,"shop/products/product_details.html",{"products":products})
      else:
        messages.error(request,"No Such Produtct Found")
        return redirect('collections')
    else:
      messages.error(request,"No Such Catagory Found")
      return redirect('collections')

joes_project/urls.py

"""joes_project URL Configuration
 
The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
 
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('shop.urls')),
]
 
if settings.DEBUG:
    urlpatterns+=static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

joes_project/settings.py

"""
Django settings for joes_project project.
 
Generated by 'django-admin startproject' using Django 4.0.6.
 
For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
 
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
 
from pathlib import Path
 
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
 
 
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
 
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-72ct@i#m$q9xs(hdhi^^xa5asb!l$81s0+u180-!k^v#+ug=hk'
 
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
 
ALLOWED_HOSTS = []
 
 
# Application definition
 
INSTALLED_APPS = [
    'jazzmin',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'shop'
]
 
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
 
ROOT_URLCONF = 'joes_project.urls'
 
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]
 
WSGI_APPLICATION = 'joes_project.wsgi.application'
 
 
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
 
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_joes',
        'HOST':'localhost',
        'USER':'root',
        'PASSWORD':'root',
        'PORT':'3306'
    }
}
 
 
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
 
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]
 
 
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
 
LANGUAGE_CODE = 'en-us'
 
TIME_ZONE = 'UTC'
 
USE_I18N = True
 
USE_TZ = True
 
 
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
 
STATIC_URL = 'static/'
 
MEDIA_URL='/images/'
MEDIA_ROOT=BASE_DIR/'static'
 
STATICFILES_DIRS=[
	BASE_DIR/'static'
]
 
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
 
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
 

Conclusion

In this article, I demonstrated how to create a E-commerce using Python Django and MySQL. Hope you can easily understand thank you "Happy Coding".