Hi everyone who reading this My english is not so good but I will try my best to explain my problem.
Ok, let’s start. I have two models - Category and Service. Category has field «parent_category» with ForeignKey ‘self’ to implement subcategories functionality. I can print my main categories and filter services by them. Also when I click on main categories, its subcategories prints fine. But when I click on subcategories, services are not filtered by them. How can I implement filtering by clicking on subcategories? Honestly say this is just my 2nd project on Django. So don’t judge strickly, please. I’m writing here in not my native language because I’m already starting to despair This forum is my last hope.
models.py
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=255, db_index=True)
slug = models.SlugField(max_length=255, db_index=True, unique=True)
parent_category = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, null=True, blank=True)
class Meta:
ordering = (['name',])
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
def __str__(self):
return self.name
def get_absolute_url(self):
if self.parent_category:
return reverse('main:service_list_by_category', args=[self.parent_category.slug, self.slug])
return reverse('main:service_list_by_category', args=[self.slug])
class Service(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='services')
name = models.CharField(max_length=255, db_index=True)
slug = models.SlugField(max_length=255, db_index=True)
description = models.TextField(blank=True)
preparation = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=0)
available = models.BooleanField(default=True)
class Meta:
ordering = (['name',])
index_together = (('id', 'slug'))
verbose_name = 'Услуга'
verbose_name_plural = 'Услуги'
def __str__(self):
return self.name
views.py
from django.shortcuts import render
from .models import Category, Service
def service_list(request, category_slug=None):
services = Service.objects.filter(available=True)
main_categories = Category.objects.filter(parent_category=None)
sub_category = None
if category_slug:
sub_category = Category.objects.get(slug=category_slug)
if sub_category.children.exists():
categories = [sub_category] + list(sub_category.children.all())
services = services.filter(category__in=categories)
else:
services = services.filter(category=sub_category)
return render(request,
'main/list.html',
{'sub_category': sub_category,
'main_categories': main_categories,
'services': services})
list.html
{% extends 'layout/base.html' %}
{% block content %}
<section>
<div class="container">
<div class="container">
{% for category in main_categories %}
<a href="{{ category.get_absolute_url }}">{{ category.name }}</a>
{% endfor %}
</div>
<div class="container">
{% for subcategory in sub_category.children.all %}
<a href="{{ category.get_absolute_url }}">{{ subcategory.name }}</a>
{% endfor %}
</div>
</div>
<div class="container" style="margin-top: 100px">
{% for service in services %}
<h6>{{ service.name }}</h6>
<p>{{ service.description }}</p>
<p>{{ service.price }}</p>
<small>{{ parent_category }}/{{ sub_category }}</small>
{% endfor %}
</div>
</section>
{% endblock %}
urls.py
from django.urls import path
from . import views
app_name = 'main'
urlpatterns = [
path('', views.service_list, name='service_list'),
path('<category_slug>/', views.service_list, name='service_list_by_category'),
]