Фильтр товаров с использованием модели категорий в Django

Я создаю сайт электронной коммерции и хочу фильтровать продукты с помощью категорий, но не знаю, как отобразить продукты. И добавить категории в навигационную панель, откуда люди могут переходить к различным категориям.

Вот мой views.py файл:

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)

А это мой 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

Я также не знаю, как отобразить его в html.

Для рендеринга вам нужно будет использовать шаблоны Django. Их не очень сложно реализовать.

Шаблон может начинаться примерно так:

<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>

Фильтрация товаров на основе категории проста:

products = Product.objects.filter(category__category='burger_buns')

Если вам нужно несколько категорий:

category_names = 'burger_buns sausages hammers'.split()
products = Product.objects.filter(category__category__in=category_names)

Или вы можете использовать обратный аксессор (подробнее здесь):

category = Category.objects.get(id=1)
products = category.product_set.all()

Я настоятельно рекомендую прочитать документацию по этому вопросу.

Когда вы определили отношение ForeignKey для Category из Product, также будет существовать обратное отношение. По умолчанию оно называется category.product_set. Поэтому в вашем шаблоне, когда пользователь выбирает экземпляр категории, вы можете получить соответствующие ей товары с помощью category1.product_set. Чтобы изменить это имя, определите related_name для отношения ForeignKey.

category = models.ForeignKey(Category, related_name="products", on_delete = models.CASCADE)

Теперь, чтобы получить доступ к соответствующим товарам категории, просто сделайте что-то вроде category1.products.

сначала нужно перейти в urls.py и сделать

urls.py в качестве примера

from .view import CategoryView 
url_patterns =[
path("products/category/<slug:slug>/,CategoryView.as_view(),name="product-category")
]

в поле зрения

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)

Ваш вопрос составлен, тогда я отвечу на вопрос о категориях (Как показывать категории в навигационной панели и переходить по ним).

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>
Вернуться на верх