Django. I can't understand the error of removing products from the catalog
I'm making a catalog, I can't understand why products are not displayed by catalog categories, it gives an error 404. The sections in the catalog work as they should. Here is the code: I am grateful in advance for any hint! models.py
`
from django.db import models
from django.urls import reverse
class Catalog_text(models.Model):
text_left = models.TextField('Text1')
text_right = models.TextField('Text2')
signature = models.CharField(max_length=255, verbose_name="Signature")
class Meta:
verbose_name = 'Text1'
verbose_name_plural = 'Text2'
class Catalog(models.Model):
sections = models.CharField(max_length=150, db_index=True, verbose_name="Name")
img = models.ImageField(upload_to='img/catalog/')
slug = models.SlugField(max_length=150, db_index=True, unique=True, null=True)
class Meta:
ordering = ('sections',)
index_together = (('id', 'slug'),)
verbose_name = 'catalog'
verbose_name_plural = 'catalogs'
def __str__(self):
return self.sections
def get_absolute_url(self):
return reverse('catalog', kwargs={"slug": self.slug})
class Category(models.Model):
catalog = models.ForeignKey(Catalog, related_name='catalog', on_delete=models.CASCADE,
verbose_name='Select a directory'
)
name = models.CharField(max_length=150, db_index=True, verbose_name="Name")
img = models.ImageField(upload_to='img/catalog/')
slug = models.SlugField(max_length=200, db_index=True, unique=True, null=True)
class Meta:
ordering = ('name',)
index_together = (('id', 'slug'),)
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog-detail', kwargs={"slug": self.slug})
class Product(models.Model):
category = models.ForeignKey(Category, related_name='category', on_delete=models.CASCADE,
verbose_name='Select a category'
)
name = models.CharField(max_length=255, db_index=True,unique=True, null=True, verbose_name="Название")
text = models.TextField('Текст')
url = models.CharField(max_length=255, db_index=True, verbose_name="Link to the website")
pdf = models.FileField(upload_to='pdf/')
slug = models.SlugField(max_length=200, db_index=True, unique=True, null=True)
class Meta:
ordering = ('name',)
index_together = (('id', 'slug'),)
verbose_name = 'Product'
verbose_name_plural = 'Products'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('product-detail', kwargs={"slug": self.slug})
class Gallery(models.Model):
image = models.ImageField(upload_to='img/catalog/')
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
class Meta:
verbose_name = 'Gallery'
verbose_name_plural = 'Galleries'
urls.py
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.CatalogView.as_view(), name='catalog'),
path('<slug>/', views.CatalogDetailViews.as_view(), name='catalog-detail'),
path('product/<slug>', views.ProductDetailViews.as_view(), name='product-detail')
]
` views.py
`
from django.shortcuts import render, get_object_or_404
from .models import Catalog_text, Catalog, Category, Product
from django.views.generic import DetailView, ListView
class CatalogView(ListView):
model = Catalog
template_name = 'catalog/catalog.html'
context_object_name = 'catalog'
class CatalogDetailViews(ListView):
model = Category
template_name = 'catalog/catalog-detail.html'
context_object_name = 'category'
def get_context_data(self, **kwargs):
context = super(CatalogDetailViews, self).get_context_data(**kwargs)
context['cat'] = Catalog.objects.all()
return context
def get_queryset(self):
category = get_object_or_404(Catalog, slug__iexact=self.kwargs.get('slug'))
queryset = category.catalog.all()
return queryset
class ProductDetailViews(DetailView):
model = Product
template_name = 'catalog/product-detail.html'
context_object_name = 'product'
` In the template:
{% for cat in category %}
<div class="room-item catalog_items">
<ul class="hover-effect-cover">
<li>
<img src="{{ cat.img.url }}" alt="">
<div class="effect-to-top">
<h3>{{ cat.name }}</h3>
<p></p>
<a href="{% url 'product-detail' cat.id %}" class="button">more detailed</a>
</div>
</li>
</ul>
</div>
{% endfor %}
Let's say I'm in the admin panel category test and product for this category product1, the link in the template turns out to be catalog/product/test and, accordingly, gives 404, but if I correct the link in the address bar to catalog/product/product1, then everything will open as it should (product description).
I guess instead of this (passing category id whereas product-detail url pattern expects product slug)
{% url 'product-detail' cat.id %}
you need this
{% url 'catalog-detail' cat.slug %}
But if you wanted to list all the products then you need nested loop for products per given category.
upd
You cannot get to "product details" just having "category id". From the perspective of category you can get to "category details" or retrieve list of category products. If you want to display list of products per category then you need something like
{% for cat in category %}
{% for prod in cat.product_set.all %}
and only after that refer to the specific product page
{% url 'product-detail' prod.slug %}