I'm building an ecommerce website and want to filter products using categories but I don't know how to render the products. And add the categories in the navigation bar from where people can navigate to different categories.
Here's my views.py file:
from django.shortcuts import render
from django.views import View
from .models import Product, Category
class ProductView(View):
def get(self, request, *args, **kwargs):
products = Product.objects.filter(is_active = True)
context = {
'products': products,
}
return render(request, 'Product/products.html', context)
class ProductDetailView(View):
def get(self, request, slug):
product = Product.objects.get(slug = slug)
context = {
'product': product
}
return render(request, 'Product/productdetail.html', context)
class CategoryView(View):
def get(self, request):
category = Category.objects.all()
products = Product.objects.filter(category__slug = slug)
context = {
'category': category,
'products':products,
}
return render(request, 'Product/category.html', context)
And this is my models.py
from django.db import models
from Seller.models import Seller
class Category(models.Model):
category = models.CharField(max_length = 255)
slug = models.SlugField(max_length = 255)
def __str__(self):
return self.category
class Product(models.Model):
product = models.ForeignKey(Seller, on_delete = models.CASCADE)
title = models.CharField(max_length = 255)
image = models.ImageField(upload_to = 'images', null = True, blank = True)
file = models.FileField(upload_to = 'files', null = True, blank = True)
actual_price = models.PositiveIntegerField(default = '0')
selling_price = models.PositiveIntegerField(default = '0')
slug = models.SlugField(max_length = 255, unique = True)
category = models.ForeignKey(Category, on_delete = models.CASCADE)
description = models.TextField()
is_active = models.BooleanField(default = True)
def __str__(self):
return self.title
I also don't know how to render it in html.
CodePudding user response:
To render you will need to use Django templates. They're not very hard to implement.
The template can start as something like this:
<html>
<body>
{% for product in products %}
<a href="products/{{ product.id }}">
<div>
<img src="{{ product.image.url }}">
<div>
<h3> {{ product.title }}</h3>
<p> {{ product.description|linebreaks }}</p>
</div>
</div>
</a>
{% endfor%}
</body>
</html>
Filtering products based on category is simple:
products = Product.objects.filter(category__category='burger_buns')
If you want multiple categories:
category_names = 'burger_buns sausages hammers'.split()
products = Product.objects.filter(category__category__in=category_names)
Or you can use the reverse accessor (more here):
category = Category.objects.get(id=1)
products = category.product_set.all()
I highly recommend reading the docs on this.
CodePudding user response:
When you defined the ForeignKey relation to Category
from Product
, there'll also be a backward relationship. By default is named category.product_set
. So in your template, when a user chooses a category instance, you can get its corresponding products with category1.product_set
. To change this name, define a related_name
for the ForeignKey relation.
category = models.ForeignKey(Category, related_name="products", on_delete = models.CASCADE)
now to access the category's corresponding products, just do something like category1.products
.
CodePudding user response:
Your question is composed, then i'll answer to the categories issue (How to show categories in a nav bar and go through them).
views.py
from django.views.generic.list import ListView
from .models import Category, Product
class CategoryListView(ListView):
model = Category
# Override the context_object_name, default is 'object_list'
context_object_name = 'categories'
# Assume that category_list.html is in app/templates/ folder
template_name = 'category_list.html'
class CategoryDetailView(DetailView):
model = Category
context_object_name = 'category' # Default is 'object'
# Assume that category_detail.html is in app/templates/ folder
template_name = 'category_detail.html'
# Add the product of this category to the context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# This line retrieve all the products of this category
context['products'] = self.product_set.all()
return context
urls.py
from django.urls import path
from .views import CategoryListView, CategoryDetailView
urlpatterns = [
path('category/', CategoryListView.as_view(), name='category-list'),
path('category/<slug:slug>/', CategoryDetailView.as_view(), name='category-detail'),
]
category_list.html
<h1 class="head">Products Categories</h1>
{% for cat in categories %}
<div>
<a href="{% url 'category-detail' cat.slug %}">
<h3>{{ cat.category }}</h3>
</a>
</div>
{% endfor %}
</div>
category_detail.html
<h1 class="head">{{ category.category }}</h1>
<h3>Products for this category</h3>
<div>
{% for product in products %}
<div>
<h5>{{ product.title }}<h5/>
<div>{{ product.description }}</div>
<img src="{{ product.image.url }}"/>
</div>
{% endfor %}
</div>
CodePudding user response:
first, you need to go to urls.py and do
urls.py as an example
from .view import CategoryView
url_patterns =[
path("products/category/<slug:slug>/,CategoryView.as_view(),name="product-category")
]
in view
class CategoryView(View):
def get(self, request, slug):
category = Category.objects.all()
products = Product.objects.filter(category__slug = slug)
context = {
'category': category,
'products':products,
}
return render(request, 'Product/category.html', context)