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 }}
inindex.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 aqueryset
.
{% 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> ${{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 :
LinkedIn : https://www.linkedin.com/in/rohitrajputops/
GitHub : https://github.com/rohit-rajput1
Twitter : https://twitter.com/rohitrajput31
Instagram : https://www.instagram.com/rohitrajput_36/