How to Structure Product & Category Pages in Django

Product Page Creation
Anytime we are creating any kind of web-page in Django it's a three-step process :
First we create a URL.
Then we create a View for the same.
And last HTML template file.
- First, we'll create a URL for the product that will open the product page when clicked. To do this, go to your app's store/urls.py file.
from django.urls import path
from . import views
urlpatterns = [
path('',views.home,name='home'),
path('about/',views.about,name='about'),
path('login/',views.login_user,name='login'),
# product page redirection
path('product/<int:pk>',views.product,name='product'),
# we have created logout url but not a page because we want a redirect it to home.
path('logout/',views.logout_user,name='logout'),
path('register/',views.register_user,name='register'),
]
- Now, we'll create a view for the same URL to handle the redirection. Go to your app's store/views.py file.
from .models import Product
def product(request,pk):
product = Product.objects.get(id=pk)
return render(request,'product.html',{'product':product})
- Let's create a product.html page so that when we click on a product, it redirects to a page showing the product details based on its primary key.
{% extends 'base.html' %}
{% block content %}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Product Details</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Afacad Flux", sans-serif;
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-image:linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url(/media/uploads/product/photo-1439792675105-701e6a4ab6f0.jpeg);
padding: 20px;
}
.product-container {
background: white;
padding: 40px;
border-radius: 20px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 1000px;
display: flex;
gap: 40px;
}
/* Product Image Section */
.product-image {
flex: 1;
min-width: 0; /* Prevents image from overflowing */
}
.product-image img {
width: 100%;
height: auto;
border-radius: 10px;
object-fit: cover;
}
/* Product Details Section */
.product-details {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0; /* Prevents content from overflowing */
}
.product-title {
font-size: 32px;
color: #333;
margin-bottom: 16px;
line-height: 1.2;
}
.product-description {
color: #666;
font-size: 16px;
line-height: 1.6;
margin-bottom: 24px;
}
.product-price {
font-size: 28px;
color: #00cc66;
font-weight: 600;
margin-bottom: 32px;
}
.home-button {
background: #00cc66;
color: white;
border: none;
padding: 14px 28px;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
align-self: flex-start;
text-decoration: none;
display: inline-block;
}
.home-button:hover {
background: #00b359;
}
/* Responsive Design */
@media (max-width: 768px) {
.product-container {
flex-direction: column;
padding: 24px;
}
.product-image {
margin-bottom: 24px;
}
.product-title {
font-size: 24px;
}
.product-price {
font-size: 24px;
margin-bottom: 24px;
}
.home-button {
width: 100%;
text-align: center;
}
}
/* Optional: Add image zoom effect on hover */
.product-image {
overflow: hidden;
}
.product-image img {
transition: transform 0.3s ease;
}
.product-image img:hover {
transform: scale(1.05);
}
</style>
</head>
<body>
<div class="product-container">
<!-- Product Image Section -->
<div class="product-image">
<img src="{{product.image.url}}" alt="Product Image">
</div>
<!-- Product Details Section -->
<div class="product-details">
<h1 class="product-title">{{product.name}}</h1>
<p class="product-description">
{{product.description}}
</p>
<div class="product-price">{{product.price}} $</div>
<a href="{% url 'home' %}" class="home-button">Return Home</a>
</div>
</div>
</body>
{% endblock %}
What does path('product/<int:pk>', views.product, name='product') do?
path('product/<int:pk>', views.product, name='product')defines a URL pattern in Django.'product/<int:pk>'is the URL path where:'product/'is the base URL.'<int:pk>'captures an integer (primary key) from the URL and passes it to the view aspk.
views.productis the view function that handles the request and displays the product page based on thepk.name='product'assigns a name to the URL, allowing you to reference it in templates or redirects using{% url 'product' pk %}.

- We’ll also add a Cart icon to the homepage since an e-commerce platform isn’t complete without a cart for that go to templates/navbar.html which is added at the end of the navbar code.
<li class="nav__item"></li>
<head>
<style>
.btn-cart {
display: flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
border-radius: 8px;
border: none;
background-color: transparent;
position: relative;
}
.btn-cart::after {
content: attr(data-quantity);
width: fit-content;
height: fit-content;
position: absolute;
font-size: 15px;
color: white;
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
opacity: 0;
visibility: hidden;
transition: .2s linear;
top: 100%;
}
.icon-cart {
width: 25px;
height: 31px;
transition: .2s linear;
}
.icon-cart path {
fill: rgb(240, 8, 8);
transition: .2s linear;
}
.btn-cart:hover > .icon-cart {
transform: scale(1.2);
}
.btn-cart:hover > .icon-cart path {
fill: rgb(186, 34, 233);
}
.btn-cart:hover::after {
visibility: visible;
opacity: 1;
top: 100%;
}
.quantity {
display: none;
}
</style>
</head>
<body>
<button data-quantity="0" class="btn-cart">
<svg class="icon-cart" viewBox="0 0 24.38 30.52" height="30.52" width="24.38" xmlns="http://www.w3.org/2000/svg">
<!-- <title>icon-cart</title> -->
<path transform="translate(-3.62 -0.85)" d="M28,27.3,26.24,7.51a.75.75,0,0,0-.76-.69h-3.7a6,6,0,0,0-12,0H6.13a.76.76,0,0,0-.76.69L3.62,27.3v.07a4.29,4.29,0,0,0,4.52,4H23.48a4.29,4.29,0,0,0,4.52-4ZM15.81,2.37a4.47,4.47,0,0,1,4.46,4.45H11.35a4.47,4.47,0,0,1,4.46-4.45Zm7.67,27.48H8.13a2.79,2.79,0,0,1-3-2.45L6.83,8.34h3V11a.76.76,0,0,0,1.52,0V8.34h8.92V11a.76.76,0,0,0,1.52,0V8.34h3L26.48,27.4a2.79,2.79,0,0,1-3,2.44Zm0,0"></path>
</svg>
<span class="quantity"></span>
</button>
</body>
</li>
</ul>

Product Category Page Drop-down (Icon)
- First, we'll add the drop-down menu for the "Featured Category" in navbar.html. This drop-down will include three options: Sports, Kids, and Luxury. We'll also apply inline CSS for styling.
<li class="nav__item">
<!-- Dropdown Menu -->
<div class="select">
<div class="selected" data-default="Feature" data-sports="Sports" data-kids="Kids" data-luxury="Luxury">
Featured
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" class="arrow">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"></path>
</svg>
</div>
<div class="options">
<div title="sports">
<input id="sports" name="option" type="radio" />
<label class="option" for="sports" data-txt="Sports"></label>
</div>
<div title="kids">
<input id="kids" name="option" type="radio" />
<label class="option" for="kids" data-txt="Kids"></label>
</div>
<div title="luxury">
<input id="luxury" name="option" type="radio" />
<label class="option" for="luxury" data-txt="Luxury"></label>
</div>
</div>
</div>
</li>
<style>
/* Only modified dropdown related styles */
.select {
width: fit-content;
cursor: pointer;
position: relative;
transition: 300ms;
color: white;
overflow: visible; /* Changed from hidden to visible */
}
.selected {
background-color: #76c557;
padding: 6px;
margin-bottom: 1px;
border-radius: 5px;
position: relative;
z-index: 10;
font-size: 15.5px;
display: flex;
align-items: center;
justify-content: space-between;
}
.arrow {
position: relative;
right: 0px;
height: 10px;
transform: rotate(-90deg);
width: 25px;
fill: white;
z-index: 10;
transition: 300ms;
}
.options {
display: flex;
flex-direction: column;
border-radius: 5px;
padding: 5px;
background-color: #2a2f3b;
position: absolute; /* Changed from relative to absolute */
top: 100%; /* Position below the selector */
left: 0;
opacity: 0;
visibility: hidden; /* Added for better control */
transition: 300ms;
z-index: 20; /* Higher than other elements */
}
.select:hover > .options {
opacity: 1;
visibility: visible;
top: 100%; /* Maintain position below selector */
}
/* All other CSS remains unchanged from your original */
.select:hover > .selected .arrow {
transform: rotate(0deg);
}
.option {
border-radius: 5px;
padding: 5px;
transition: 300ms;
background-color: #2a2f3b;
width: 150px;
font-size: 15px;
}
.option:hover {
background-color: #323741;
}
.options input[type="radio"] {
display: none;
}
.options label {
display: inline-block;
}
.options label::before {
content: attr(data-txt);
}
.options input[type="radio"]:checked + label {
display: none;
}
.options input[type="radio"]#all:checked + label {
display: none;
}
.select:has(.options input[type="radio"]#all:checked) .selected::before {
content: attr(data-default);
}
.select:has(.options input[type="radio"]#option-1:checked) .selected::before {
content: attr(data-one);
}
.select:has(.options input[type="radio"]#option-2:checked) .selected::before {
content: attr(data-two);
}
.select:has(.options input[type="radio"]#option-3:checked) .selected::before {
content: attr(data-three);
}
</style>

- Next, we need to create a category page for these options. At the same time, we'll set up the categories in the backend so that products can be assigned accordingly.

- Thus, we have linked each product to its respective category in the backend through the admin panel.

Product Category Pages
- To begin, we will define the URL for the category page in
urls.py.
from django.urls import path
from . import views
urlpatterns = [
# Feature category for the product page
path('category/<str:foo>/', views.category, name="category"),
]
- After defining the URL, we will proceed to create the view for our category page in
views.py.
from .models import Product, Category
def category(request, foo):
# Convert to lowercase to make it case-insensitive
# This will handle both 'Luxury' and 'luxury' from the URL
foo = foo.replace('-', '').lower()
# Grab the category name from the url and get the products with that category name
try:
# Use the correct model name capitalization (Category, not category)
# And search case-insensitive
category = Category.objects.get(name__iexact=foo)
# Use the correct method name (objects, not object)
products = Product.objects.filter(category=category)
return render(request, 'category.html', {'category': category.name, 'products': products})
except:
messages.success(request, "Category does not exist")
return redirect('home')
- Now that we have set up the URLs and views, the next step is to create the category.html template. In this template, we will use Django template tags to dynamically fetch and display images and links correctly.
{% extends 'base.html' %}
{% block content %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ category }} Watches Collection</title>
<style>
/* Core Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Afacad Flux", sans-serif;
}
body {
background-color: #121212;
color: #f5f5f5;
min-height: 100vh;
}
/* Hero Section */
.hero {
position: relative;
height: 60vh;
min-height: 400px;
display: flex;
align-items: center;
overflow: hidden;
}
.hero-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),
url('/placeholder.svg?height=800&width=1600') center/cover no-repeat;
}
/* Add a subtle gradient overlay */
.hero::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(18, 18, 18, 0) 0%, rgba(18, 18, 18, 1) 100%);
z-index: 1;
}
.container {
width: 100%;
max-width: 1300px;
margin: 0 auto;
padding: 0 40px;
position: relative;
z-index: 2;
}
.hero-content {
max-width: 700px;
}
.category-badge {
display: inline-block;
background-color: #d4af37;
color: #000;
padding: 6px 12px;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 2px;
border-radius: 3px;
margin-bottom: 16px;
}
.category-title {
font-size: 56px;
font-weight: 700;
line-height: 1.1;
margin-bottom: 20px;
background: linear-gradient(45deg, #ffffff, #d4af37);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-transform: uppercase;
}
.category-description {
font-size: 18px;
line-height: 1.7;
color: #ccc;
margin-bottom: 30px;
max-width: 600px;
}
.explore-btn {
display: inline-block;
background: linear-gradient(45deg, #d4af37, #f5cc5d);
color: #000;
padding: 12px 28px;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
border-radius: 4px;
text-decoration: none;
transition: all 0.3s ease;
border: none;
cursor: pointer;
}
.explore-btn:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(212, 175, 55, 0.2);
}
/* Products Section */
.products-section {
padding: 80px 0;
position: relative;
}
/* Decorative elements */
.decorative-line {
height: 3px;
width: 80px;
background: linear-gradient(90deg, #d4af37, transparent);
margin-bottom: 16px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 50px;
}
.section-title {
font-size: 32px;
font-weight: 600;
color: #fff;
position: relative;
}
.filter-controls {
display: flex;
gap: 15px;
}
.filter-btn {
background-color: transparent;
color: #ccc;
border: 1px solid #333;
padding: 8px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn.active, .filter-btn:hover {
background-color: #d4af37;
color: #000;
border-color: #d4af37;
}
/* Products Grid */
.products-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 30px;
}
/* Product Card */
.product-card {
background-color: #1a1a1a;
border-radius: 8px;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
height: 100%;
display: flex;
flex-direction: column;
position: relative;
border: 1px solid #2a2a2a;
}
.product-card:hover {
transform: translateY(-10px);
box-shadow: 0 20px 30px rgba(0, 0, 0, 0.4);
border-color: #d4af37;
}
.card-image-wrapper {
position: relative;
overflow: hidden;
width: 100%;
height: 250px;
}
.product-image {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.7s ease;
}
.product-card:hover .product-image {
transform: scale(1.07);
}
.card-overlay {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 60%;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
opacity: 0;
transition: opacity 0.3s ease;
}
.product-card:hover .card-overlay {
opacity: 1;
}
.quick-actions {
position: absolute;
top: 15px;
right: 15px;
display: flex;
flex-direction: column;
gap: 10px;
opacity: 0;
transform: translateX(20px);
transition: all 0.3s ease;
}
.product-card:hover .quick-actions {
opacity: 1;
transform: translateX(0);
}
.action-btn {
width: 36px;
height: 36px;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 50%;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.action-btn:hover {
background-color: #d4af37;
}
.action-icon {
width: 16px;
height: 16px;
fill: white;
}
.sale-badge {
position: absolute;
top: 15px;
left: 15px;
background: linear-gradient(45deg, #d4af37, #f5cc5d);
color: #000;
padding: 5px 12px;
font-size: 12px;
font-weight: 600;
border-radius: 3px;
text-transform: uppercase;
letter-spacing: 1px;
z-index: 1;
}
.product-details {
padding: 20px;
flex-grow: 1;
display: flex;
flex-direction: column;
position: relative;
z-index: 1;
}
.product-category {
font-size: 12px;
color: #999;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 5px;
}
.product-name {
font-size: 18px;
font-weight: 600;
margin-bottom: 10px;
color: #fff;
transition: color 0.3s ease;
}
.product-card:hover .product-name {
color: #d4af37;
}
.product-rating {
display: flex;
align-items: center;
margin: 10px 0;
gap: 2px;
}
.star {
color: #d4af37;
font-size: 14px;
}
.rating-count {
font-size: 12px;
color: #999;
margin-left: 8px;
}
.product-price {
margin-top: auto;
font-size: 18px;
font-weight: 600;
color: #fff;
display: flex;
align-items: center;
gap: 10px;
}
.sale-price {
color: #d4af37;
}
.original-price {
text-decoration: line-through;
color: #999;
font-weight: 400;
font-size: 16px;
}
.product-footer {
padding: 15px 20px;
background-color: #222;
border-top: 1px solid #2a2a2a;
transition: background-color 0.3s ease;
}
.product-card:hover .product-footer {
background-color: #1a1a1a;
}
.view-button {
display: block;
width: 100%;
padding: 12px 0;
background-color: transparent;
color: #fff;
border: 1px solid #d4af37;
border-radius: 4px;
text-align: center;
text-decoration: none;
font-weight: 500;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 1px;
transition: all 0.3s ease;
cursor: pointer;
}
.view-button:hover {
background-color: #d4af37;
color: #000;
}
/* Pagination Section */
.pagination {
display: flex;
justify-content: center;
margin-top: 60px;
gap: 10px;
}
.page-link {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
font-weight: 500;
background-color: #1a1a1a;
color: #fff;
text-decoration: none;
transition: all 0.3s ease;
border: 1px solid #2a2a2a;
}
.page-link:hover, .page-link.active {
background-color: #d4af37;
color: #000;
border-color: #d4af37;
}
/* Footer CTA Section */
.cta-section {
padding: 80px 0;
background-color: #1a1a1a;
margin-top: 80px;
position: relative;
overflow: hidden;
}
.cta-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 50px;
align-items: center;
}
.cta-image {
width: 100%;
height: 400px;
object-fit: cover;
border-radius: 8px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}
.cta-content {
padding-right: 30px;
}
.cta-subtitle {
font-size: 14px;
text-transform: uppercase;
letter-spacing: 2px;
color: #d4af37;
margin-bottom: 15px;
}
.cta-title {
font-size: 36px;
font-weight: 700;
margin-bottom: 20px;
color: #fff;
}
.cta-text {
font-size: 16px;
line-height: 1.7;
color: #ccc;
margin-bottom: 30px;
}
/* Responsive Design */
@media (max-width: 1200px) {
.container {
padding: 0 30px;
}
.products-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 992px) {
.category-title {
font-size: 44px;
}
.products-grid {
grid-template-columns: repeat(2, 1fr);
}
.cta-grid {
grid-template-columns: 1fr;
gap: 30px;
}
.cta-content {
padding-right: 0;
}
}
@media (max-width: 768px) {
.container {
padding: 0 20px;
}
.category-title {
font-size: 36px;
}
.hero {
height: auto;
padding: 80px 0;
}
.section-header {
flex-direction: column;
align-items: flex-start;
gap: 20px;
}
.filter-controls {
width: 100%;
overflow-x: auto;
padding-bottom: 10px;
}
}
@media (max-width: 576px) {
.category-title {
font-size: 32px;
}
.products-grid {
grid-template-columns: 1fr;
}
.cta-title {
font-size: 28px;
}
}
</style>
</head>
<body>
<!-- Hero Section -->
<section class="hero">
<div class="hero-background"></div>
<div class="container">
<div class="hero-content">
<div class="category-badge">Collection: LUX-W2023</div>
<h1 class="category-title">{{ category }}</h1>
<p class="category-description">Discover our exclusive collection of premium watches, crafted with precision and elegance. Each timepiece represents the perfect blend of innovation, craftsmanship, and timeless design.</p>
<a href="#products" class="explore-btn">Explore Collection</a>
</div>
</div>
</section>
<!-- Products Section -->
<section id="products" class="products-section">
<div class="container">
<div class="section-header">
<div>
<div class="decorative-line"></div>
<h2 class="section-title">{{ category }} Collection</h2>
</div>
<div class="filter-controls">
<button class="filter-btn active">All</button>
<button class="filter-btn">New Arrivals</button>
<button class="filter-btn">Best Sellers</button>
<button class="filter-btn">Sale</button>
</div>
</div>
<div class="products-grid">
{% for product in products %}
<div class="product-card">
{% if product.is_sale %}
<div class="sale-badge">Sale</div>
{% endif %}
<div class="card-image-wrapper">
<img src="{{ product.image.url|default:'/placeholder.svg?height=300&width=300' }}" alt="{{ product.name }}" class="product-image">
<div class="card-overlay"></div>
<div class="quick-actions">
<button class="action-btn">
<svg class="action-icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/>
</svg>
</button>
<button class="action-btn">
<svg class="action-icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
</svg>
</button>
</div>
</div>
<div class="product-details">
<div class="product-category">{{ category }}</div>
<h3 class="product-name">{{ product.name }}</h3>
<div class="product-rating">
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="star">★</span>
<span class="rating-count">({{ product.rating|default:'5.0' }})</span>
</div>
{% if product.is_sale %}
<div class="product-price">
<span class="sale-price">${{ product.sale_price }}</span>
<span class="original-price">${{ product.price }}</span>
</div>
{% else %}
<div class="product-price">${{ product.price }}</div>
{% endif %}
</div>
<div class="product-footer">
<a href="{% url 'product' product.id %}" class="view-button">View Details</a>
</div>
</div>
{% empty %}
<div class="no-products-message">
<p>No products available in this category yet. Check back soon!</p>
</div>
{% endfor %}
</div>
<!-- Pagination -->
<div class="pagination">
<a href="#" class="page-link">1</a>
<a href="#" class="page-link active">2</a>
<a href="#" class="page-link">3</a>
<a href="#" class="page-link">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="9 18 15 12 9 6"></polyline>
</svg>
</a>
</div>
</div>
</section>
<!-- Call to Action Section -->
<section class="cta-section">
<div class="container">
<div class="cta-grid">
<div class="cta-content">
<div class="cta-subtitle">Limited Time Offer</div>
<h2 class="cta-title">Exclusive Collection Preview</h2>
<p class="cta-text">Be among the first to experience our newest {{ category }} watches. Sign up for our newsletter and receive exclusive updates, early access to limited editions, and special offers tailored to your preferences.</p>
<a href="#" class="explore-btn">Subscribe Now</a>
</div>
<img src="/placeholder.svg?height=400&width=600" alt="Exclusive Collection Preview" class="cta-image">
</div>
</div>
</section>
</body>
{% endblock %}
</html>
- Before checking if the redirection works on the "Featured" section, we need to update navbar.html. This involves adding URL tags for the category page in the dropdown menu to prevent errors.
<div class="select">
<div class="selected" data-default="Feature" data-sports="Sports" data-kids="Kids" data-luxury="Luxury">
Featured
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" class="arrow">
<path d="M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z"></path>
</svg>
</div>
<div class="options">
<div title="sports">
<input id="sports" name="option" type="radio" />
<label class="option" for="sports">
<a href="{% url 'category' 'Sports' %}">Sports</a>
</label>
</div>
<div title="kids">
<input id="kids" name="option" type="radio" />
<label class="option" for="kids">
<a href="{% url 'category' 'Kids' %}">Kids</a>
</label>
</div>
<div title="luxury">
<input id="luxury" name="option" type="radio" />
<label class="option" for="luxury">
<a href="{% url 'category' 'Luxury' %}">Luxury</a>
</label>
</div>
</div>
</div>
- Start the Django server to verify that the products & category are correctly fetched into their designated fields.
python manage.py runserver

Similarly, we can create additional pages for the website as needed, ensuring a structured and user-friendly experience.
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/



