Adding Product Pages in Django: A Step-by-Step Guide

Adding Product Pages in Django: A Step-by-Step Guide

Previous Related Blog : How to Set Up a Django Frontend: A Complete Tutorial

Today, we will extend the homepage by adding a "Related Products" section to showcase more products. We will write HTML and CSS to ensure it is well-aligned and remains responsive across different devices.

Grid Layout Template Creation

  • Let’s create an HTML card template in templates/index.html to display products in a grid layout:
<h1 class="related-product">Related Products</h1>
        <div class="container card-container">
            {{ products }}
     x       <!-- Card 1 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 1</h5>
                    <p class="card-text">This is the content of Card 1.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>

            <!-- Card 2 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 2</h5>
                    <p class="card-text">This is the content of Card 2.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>

            <!-- Card 3 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 3</h5>
                    <p class="card-text">This is the content of Card 3.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>

            <!-- Card 4 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 4</h5>
                    <p class="card-text">This is the content of Card 4.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>

            <!-- Card 5 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 5</h5>
                    <p class="card-text">This is the content of Card 5.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>

            <!-- Card 6 -->
            <div class="card">
                <img src="https://via.placeholder.com/150" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">Card 6</h5>
                    <p class="card-text">This is the content of Card 6.</p>
                    <a href="#" class="btn btn-primary">Go somewhere</a>
                </div>
            </div>
        </div>

Adding CSS to Layout

  • After creating the HTML card template, we will add CSS in static/css/styles.css it to match the website theme and ensure it is responsive.
.card-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem; /* Gap between cards */
    justify-content: space-between;
    padding-block: 2rem;
}

.related-product {
    grid-column: 1 / -1; /* Make the h1 span the entire row */
    text-align: center;
    font-size: 2.5rem;
    margin-bottom: 1.5rem;
    color: var(--title-color);
}
.card {
    flex: 1 1 calc(33.33% - 1rem); /* 3 cards per row */
    background-color: var(--body-color);
    color: var(--text-color);
    border: 1px solid hsl(0, 0%, 30%);
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    transition: transform 0.2s, box-shadow 0.2s;
    font-family: var(--body-font);
}

.card:hover {
    transform: scale(1.05);
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}

.card-img-top {
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-bottom: 1px solid hsl(0, 0%, 30%);
}

.card-body {
    padding: 1rem;
}

.card-title {
    font-size: var(--h1-font-size);
    font-weight: var(--font-semi-bold);
    color: var(--title-color);
    margin-bottom: 0.5rem;
}

.card-text {
    font-size: var(--normal-font-size);
    margin-bottom: 1rem;
}

.btn-primary {
    background-color: hsl(220, 60%, 50%);
    color: var(--title-color);
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
}

.btn-primary:hover {
    background-color: hsl(220, 60%, 40%);
}

/* Responsive Adjustments */
@media screen and (max-width: 1023px) {
    .card {
        flex: 1 1 calc(50% - 1rem); /* 2 cards per row */
    }
}

@media screen and (max-width: 576px) {
    .card {
        flex: 1 1 100%; /* 1 card per row */
    }
}
  • This will display cards without images, which we will add later in this blog.

💡
Note : Since the backend isn’t connected to the frontend yet, and we can’t log in or perform actions on the website, we’ll manage everything through the Admin Panel http://localhost:8000/admin/.

Product Category

  • First, we will go to the Django Admin Panel and create a category for Watches. After this, add the related products under this category.

  • Remember, we created the Product model in models.py, where we established a relation with the Category model. This allows us to add the product's image, name, and price linked to specific categories.

  • Likewise, we will upload the product images in the Django Admin Area along with the product name and price.

  • Now, we will import the Product model (with the images) from models.py into the views of our app to display them on the frontend.

from django.shortcuts import render
from .models import Product

def home(request):
    products = Product.objects.all()
    return render(request, 'index.html', {'products':products})
  • Using {{ product }} in index.html to check if the product list has been fetched correctly.

🤔
Now, our main task is to add all the images from the backend to the empty image tiles. How we are going to do that ??

Usage of {% for %} in Django Templates :

  • In Django templates, the {% for %} and {% endfor %} tags are used to create loops that iterate over a list or a queryset.
{% for item in items %}
    {{ item }}
{% endfor %}
# items : is the list or queryset we're iterating over.
# item : is a variable that represents the current item in the loop.
  • Let’s create a similar list or queryset for the related products in index.html so that the product images are fetched in the appropriate fields.
<h1 class="related-product">Related Products</h1>
<div class="container card-container">
    {% for product in products %}
    <!-- Card 1 -->
    <div class="card">
        <img src="{{ product.image.url }}" class="card-img-top" alt="Card Image">
            <div class="card-body">
                <h5 class="card-title">{{product.name}}</h5>
                <p class="card-text">{{product.price}}</p>
                <a href="#" class="btn btn-primary">View options</a>
            </div>
    </div>
    {% endfor %}
</div>
  • Save the index.html file and run the Django server to check if the products are properly fetched into their designated fields.
python manage.py runserver


Feature (Adding a Sales Tag to the Products)

  • Since Django follows the MVT structure, we will first modify the Product model to include fields for sale details. For this, go to store/models.py, make the changes, and then run the migrations.
class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(default=0,max_digits=8,decimal_places=2)
    category = models.ForeignKey(Category,on_delete=models.CASCADE,default=1)
    description = models.CharField(max_length=300,default='',null=True,blank=True)
    image = models.ImageField(upload_to='uploads/product/')
    # Add Sales Details
    is_sale = models.BooleanField(default=False)
    sale_price = models.DecimalField(default=0,max_digits=8,decimal_places=2)
    def __str__(self):
        return self.name

  • Now, go to http://127.0.0.1:8000/admin and update the products with the sale details.

  • Now, we will add the sales logic in index.html using {% if %} and {% else %} tags. If a product is on sale, it will display with a sale tag, otherwise without it.
<h1 class="related-product">Related Products</h1>
<div class="container card-container">
    {% for product in products %}
        {% if product.is_sale %}
            <div class="card">
                <!-- Sale Badge -->
                <div class="badge position-absolute" style="top: 0.5rem; right: 0.5rem; background-color: rgba(39, 37, 37, 0.451); color: red; font-size: 1.15rem; padding: 0.3rem 1.5rem;">
                <b>Sale!!!</b>                    
                </div>
                <!-- Product Body -->
                <img src="{{ product.image.url }}" class="card-img-top" alt="Card Image">
                <div class="card-body">
                    <h5 class="card-title">{{product.name}}</h5>
                    <p class="card-text"> <strike>${{product.price}}</strike> &nbsp; ${{product.sale_price}}</p>
                    <a href="#" class="btn btn-primary">View options</a>
                </div>
             </div>
                {% else %}
                    <div class="card">
                    <!-- Product Body -->
                    <img src="{{ product.image.url }}" class="card-img-top" alt="Card Image">
                        <div class="card-body">
                            <h5 class="card-title">{{product.name}}</h5>
                            <p class="card-text">{{product.price}}</p>
                            <a href="#" class="btn btn-primary">View options</a>
                        </div>
                    </div>
                {% endif %}
    {% endfor %}
</div>
  • Now, run the server and check the website to see if the sales feature is working correctly.

Thus, we have successfully learned how to add product pages in Django and implement features with logic.


Connect with me :