Django Связать три модели
Подскажите как можно связать три модели Catalog, Category и Product У каждого каталога есть свои категории (их может быть несколько) а в категориях есть только один свой товар. На данный момент получилось сделать каталог и категории, но при переходе в продукт page not found 404 Вот как сейчас выглядит models.py
class Catalog(models.Model):
sections = models.CharField(max_length=150, db_index=True, verbose_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 = 'Главная страница каталога'
verbose_name_plural = 'Главная страница каталога'
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='Выбрать каталог'
)
name = models.CharField(max_length=150, db_index=True, verbose_name="Название")
img = models.ImageField(upload_to='img/catalog/')
slug = models.SlugField(max_length=200, db_index=True, unique=True, null=True)
# prod = models.ManyToManyField(to=Catalog, through='Product')
class Meta:
ordering = ('name',)
index_together = (('id', 'slug'),)
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
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='Выбрать категорию'
)
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="Ссылка на сайт")
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 = 'Продукт'
verbose_name_plural = 'Продукты'
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 = 'Галерея'
verbose_name_plural = 'Галереи'
views.py
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):
# Call the base implementation first to get a context
context = super(CatalogDetailViews, self).get_context_data(**kwargs)
# Add in a QuerySet of all the Baklawa
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'
urls.py
urlpatterns = [
path('', views.CatalogView.as_view(), name='catalog'),
path('<slug>/', views.CatalogDetailViews.as_view(), name='catalog-detail'),
path('product/<slug:slug>', views.ProductDetailViews.as_view(), name='product-detail')
]
В шаблоне html
{% for c in category %}
<div class="room-item catalog_items">
<ul class="hover-effect-cover">
<li>
<img src="{{ c.img.url }}" alt="">
<div class="effect-to-top">
<h3>{{ c.name }}</h3>
<p></p>
<a href="{% url 'product-detail' c.slug %}" class="button">КАТАЛОГИ</a>
</div>
</li>
</ul>
</div>
{% endfor %}
Допустим я в админке категория test и продукт для этой категории product1, ссылка в шаблоне получается catalog/product/test и соответственно выдает 404, но если я руками поправлю ссылу в адресной строке на catalog/product/product1 то все откроется как надо (описание продукта).