Create a E-commerce Shop with Django (Part 3)

Create a E-commerce Shop with Django
Create a E-commerce Shop with Django

In the previous Part 2 we create models for Order and in this Part 3 of Create a E-commerce Shop with Django we will make a summary of the order in the shopping cart of your Django shop.

Prerequisites

  • Django Latest Version
  • Virtual Environment
  • IDE PyCharm or Visual Studio Code

Before starting the tutorial don’t forget to activate your Virtual Environment, and the project we created in the previous tutorial.

1. Models

Open core / models.py using the edit code and add some functions in class model as follows :

  1. Class Item

Nothing is changed in the Item class because the order summary is not directly related to the Item class

2. Class OrderItem

In OrderItem class we will add some additional functions as follows

class OrderItem(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    ordered = models.BooleanField(default=False)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=1)

    def __str__(self):
        return f'{self.quantity} of {self.item.item_name}'

    def get_total_item_price(self):
        return self.quantity * self.item.price

    def get_discount_item_price(self):
        return self.quantity * self.item.discount_price

    def get_amount_saved(self):
        saved = self.get_total_item_price() - self.get_discount_item_price()
        return f'{saved:.2f}'

    def get_final_price(self):
        if self.item.discount_price:
            return self.get_discount_item_price()
        return self.get_total_item_price()
  • get_total_item_price, returns the total price value of each product item
  • get_discount_item_price, returns the total price value of each product item based on discounted prices
  • get_amount_saved, returns the value of the price saved from existing discounts
  • get_final_price, returns which function is used as a price determinant (whether using the original price or discounted price)

3. Class Order

In the Order class add a function that will calculate the total price of the order

class Order(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    items = models.ManyToManyField(OrderItem)
    start_date = models.DateTimeField(auto_now_add=True)
    ordered_date = models.DateTimeField()
    ordered = models.BooleanField(default=False)

    def __str__(self):
        return self.user.username

    def get_total_price(self):
        total = 0
        for order_item in self.items.all():
            total += order_item.get_final_price()
        return total
  • get_total_price, returns the value of the total price of all ordered product items

4. Migrate model database

Do not forget migrate your model database with the command below :

$ python manage.py migrate
$ python manage.py makemigrations

2. Views

After manage our model, now switches to the core/views.py file.

You can just just take order_summary.html and place it in the templates directory.

  1. Import
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, DetailView, View
from django.utils import timezone
from core.models import (
    Item,
    Order,
    OrderItem
)

Import all requiment library in your views.py, in django.views.generic you can see we import the View class. for the order summary views we will use this View class

2. Create OrderSummaryView

class OrderSummaryView(LoginRequiredMixin, View):
    def get(self, *args, **kwargs):

        try:
            order = Order.objects.get(user=self.request.user, ordered=False)
            context = {
                'object' : order
            }
            return render(self.request, 'core/order_summary.html', context)
        except ObjectDoesNotExist:
            messages.error(self.request, "You do not have an order")
            return redirect("/")

In the OrderSummaryView class we use the Order model as the model and order_summary.html as tempalate.

3. Create reduce quantity product

In the previous tutorial we made 2 function: add_to_cart() and remove_from_cart(). 

add_to_cart() make the quantiy of product adding but remove_from_cart() function will make all order removed. So we will make function that will reduce a quantity of product item and remove it if quantity equal to 0

def reduce_quantity_item(request, pk):
    item = get_object_or_404(Item, pk=pk)
    order_qs = Order.objects.filter(
        user = request.user,
        ordered=False
    )
    if order_qs.exists():
        order = order_qs[0]
        if order.items.filter(item__pk=item.pk).exists():
            order_item = OrderItem.objects.filter(
                item = item,
                user = request.user,
                ordered = False
            )[0]
            if order_item.quantity > 1:
                order_item.quantity -= 1
                order_item.save()
            else:
                order_item.delete()
            messages.info(request, "Item quantity is updated")
            return redirect("core:order-summary")
        else:
            messages.info(request, "This item not in your cart")
            return redirect("core:product")
    else:
        messages.info(request, "You do not have an order")
        return redirect("core:product")

4. Make an user must log in to make an order

For each function add an @login_required annotation, where this will throw the user into the login page when running the function if the user has not logged in

@login_required
def add_to_cart(request, pk):
   ...
@login_required
def remove_from_cart(request, pk):
   ...
@login_required
def reduce_quantity_item(request, pk):
   ...

3. Urls

After completing the view, we will now add the OrderSummaryView url and the reduce_quantity item function in the core/url.py file

  1. Import
from django.urls import path
from .views import (
    remove_from_cart,
    reduce_quantity_item,
    add_to_cart,
    ProductView,
    HomeView,
    OrderSummaryView
)

add all the views and functions that we made in the views.py file on import, so we just add OrderSummaryView and reduce_quantity_item from the previous file.

2. Create Path Url

Create path url to OrderSummaryView and reduce_quantity_item() function like this :

urlpatterns = [
    ...
    path('order-summary/', OrderSummaryView.as_view(), name="order-summary"),
    path('reduce-quantity-item/<int:pk>', reduce_quantity_item, name='reduce-quantity-item'),
]

And now you can access the view and another functions.

Proceed to the next part!

I hope you’ve found the third part of this tutorial helpful. In the next session, we’re going to make Checkout form to this E-Commerce Website.

You can visit github where find other scripts.

Автор Serhii Kupriienko

I have a multifaceted experience, accomplished several successful projects, including national-scale, modernized a museum, engaged in online commerce, wholesale and retail sales, was an entrepreneur, publisher, and editor. I headed the development department. I gave lectures and training. I organized events and press conferences. I was the secretary of the collegial boards. And I also did the planning and reporting in an organization. My Ph.D. thesis was “The social and economic system of the Inca Empire Tawantinsuyu“.

KUPRIENKO