BUILDING E-COMMERCE WEBSITE USING DJANGO PYTHON: ORDER PLACEMENT AND CHECK OUT FORM(PART - 08)

in Programming/Dev5 months ago

Hello Everyone, we are actually towards the end of the series. This is going to be the second last post of this series for now. In the future, I will be adding some new functionalities like pagination, sending pdf in email, hosting the application in AWS and so on. In this tutorial, we will be working with placing order and implementing check out, which is a common functionality in every e-commerce website. To start with this, you need to have everything from where we last left. If not, you can visit each part of this series along with the source code that is provided at the bottom of each post. Please find it below.

First Part: Getting Started
Second Part: Admin, Models and Data Rendering
Third Part: Template Inheritance, Bootstrap and Static Files
Fourth Part: Signup Form Validation
Fifth Part: Login Functionality, Admin Dashboard Customization
Sixth Part: Add to Cart Functionality
Seventh Part: Hiding Navbars, Logout, Fetching Cart Products and Using Django Filter for Currency


When the user checks out from our site, we want their items in cart to be saved as order in the database. So, for this we will create a new model called "Order" inside our store/models.py. For customer order, we will store their name, product, quantity, price, address, contact number and date when their order was placed. Customer name and product will have reference to our previous models Customer and Product respectively. So, we will use Foreign Key references for those. And lets suppose if Customer model is deleted then we want to delete the customer information in our Order model and same goes with the Product model. So we will use extra parameters for these two called on_delete=models.CASCADE while creating the database for order. Also, the datetime will be the time when they click on checkout form. So we will import datetime and write this code inside store/models.py.

import datetime

class Order(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    quantity = models.IntegerField()
    price = models.IntegerField()
    address = models.CharField(max_length=100)
    phone = models.CharField(max_length=10)
    date = models.DateTimeField(default=datetime.datetime.today)


Now we need to prepare database table for our model by using command python manage.py makemigrations in our terminal. After that we actually need to reflect the changes in the database by typing python manage.py migrate. My terminal looks like this after typing those commands.

image.png

Now to show our Order model in admin dashboard, we need to register the model. For this go to store/admin.py and put in the following code:

admin.site.register(Order)


Now lets see in our dashboard if there is an Order model. For this type python manage.py runserver to run our server. There should be no error upto this point, go to your browser and type http://127.0.0.1:8000/admin/. If it prompts to login page, use previously registered username and password to login. The dashboard now looks like this:

image.png

Clicking Orders and then Add Order will give you following screen.

image.png

Now its time to populate these fields from our front-end. Now we need to design our check out form. I will use bootstrap form for this one. Go to store/templates/store and create a new HTML file and save it as checkout.html. This code goes inside the same file. Everything like extends, block content, csrf_token has been explained in the previous tutorial so that I don't have to explain it here on what it does.

{% extends 'store/base.html' %}

{% block content %}

<div class="container text-white pt-5">
    <div class="p-5 m-5">
        <div class="col-md-6 mx-auto pt-4 bg-dark">
            <h3 class="text-white text-center pb-2">Check Out</h3>
            <form method="post" action="{% url 'checkout' %}">
                {% csrf_token %}
                <div class="form-group">
                    <label for="address">Address</label>
                    <input type="text" name="address" class="form-control" placeholder="Your address">
                </div>
                <div class="form-group">
                    <label for="phone">Phone</label>
                    <input type="text" name="phone" class="form-control" placeholder="Your phone">
                </div>
                <div class="form-group">
                    <input type="submit" value="Checkout" class="btn btn-primary mt-1 mr-2 mb-3">
                </div>
            </form>
        </div>
    </div>
</div>

{% endblock %}


In the form action method, we have used Django dynamic URL routing syntax for user to redirect them to the same page after clicking check out. And we need to create same URLs path. Go to store/urls.py and define a url path as:

path('checkout/', views.checkout, name="checkout")


Now lets create a view to check how our check out form looks. Go to store/views.py and define a simple check out view.

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


Also, we need to show check out page when user clicks on Check Out in the cart page. For this we have to use Django dynamic URL routing. Open templates/store/cart.html and add replace the Check out anchor tag link with: <a href="{% url 'checkout' %}" class="btn btn-primary float-right">Checkout</a>.

Now, lets finally run the server to see how checkout form looks. If you click on Checkout in the cart page, you will see this in the next screen.

image.png

Now, its time to save all these information in the database. We will get address and phone from this checkout field for our Order model. Customer information can be acquired from the session. Similarly we can get product quantities and price from the cart session. To get product information like name, category we need to apply our previously created method called get_products_by_id from the cart. We will grab keys of the cart, which is nothing but product ids as discussed earlier and these ids will be passed to this function to get relevant information about products. For now lets print these informations in our terminal to see if they are working. Replace your Order view in store/views.py with the following code.

def checkout(request):
    if request.method == "POST":
        address = request.POST.get("address")
        phone = request.POST.get("phone")
        customer = request.session.get("customer")
        cart = request.session.get("cart")
        products = Product.get_products_by_id(list(cart.keys()))
        print(address, phone, customer, cart, products)
        return redirect("cart")
    else:
        return render(request, 'store/checkout.html')


This is my cart page for now:

image.png

I filled out these details in the checkout page:

image.png

If you clicked checkout and see the terminal, the following long statement can be seen:

image.png

You can see our address, phone, cart products and products name are printed. Now its time to save these information in our database table inside Order. We want to create a separate order for each product items. For example: if you have three products with different quantities in your cart, then after checkout you should have three different orders. So we will be iterating over our products to save order. And after saving the order we want our cart to be empty, so will set our cart session to an empty dictionary.

To do this lets replace the checkout view inside store/views.py with the following final code:

def checkout(request):
    if request.method == "POST":
        address = request.POST.get("address")
        phone = request.POST.get("phone")
        customer = request.session.get("customer")
        cart = request.session.get("cart")
        products = Product.get_products_by_id(list(cart.keys()))

        for product in products:
            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")
    else:
        return render(request, 'store/checkout.html') 



I did checkout with above cart items and same address and phone. When, I hit checkout, then empty cart page appears as we designed.

image.png

Now lets check in the dashboard, if there are orders.

image.png

So as I added four items to the cart, there are total of 4 orders. Now lets check one of them by clicking them:

image.png

Every fields in the dashboard has been populated as we expected it to be. Now, we can check out and place order for our items in the cart. This marks the end of our tutorial for now.


Find the eighth part source code here.
Find the sample product images here.

Getting Started

Admin Dashboard link: http://127.0.0.1:8000/admin/
Username: testuser
Password: testuser321

Note: All the user in the dashboard has been saved with common password i.e. demo123 if you like to test the functionality of the project.

Sort:  

Thanks for the contribution here, this is really useful.

Welcome. I liked posting here while learning at the same time.