I use Slugs to address the URL. It all works but when I want to show product details. I don't know how can I get two slugs from another model and put it beside the details slug.
(the category is in the main URL)
(show me all products Samsung mobile)
Works: site.com/category/mobile/samsung/
(I want when I want to click one of them, show me the details, but it doesn't work)
Doesn't Work: site.com/category/mobile/samsung/s10
Model:
from Django.db import models
from Django.shortcuts import reverse
class Category(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField(unique=True, max_length=200)
child_category = models.ForeignKey('self', max_length=150, null=True, blank=True, on_delete=models.CASCADE)
is_child = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('shop:brands', args=[self.slug])
def get_absolute_url_product(self):
return reverse('shop:products', args=[self.child_category.slug, self.slug])
class Product(models.Model):
category = models.ManyToManyField(to=Category, related_name='products')
name = models.CharField(max_length=150)
slug = models.SlugField(unique=True, max_length=200)
description = models.TextField()
# Here I did what I knew, but It didn't work.
===============================================
def get_absolute_url_details(self):
return reverse('shop:product_details',
self.category.model.slug,
self.category.model.child_category.slug,
self.slug)
When I use this reverse way, it gives me this Error: 'ForwardManyToOneDescriptor' object has no attribute 'slug'
URL:
from Django.urls import path
from Shop import views
app_name = 'shop'
urlpatterns = [
path('<slug:brands_slug>/', views.brands, name='brands'),
path('<slug:brands_slug>/<slug:product_slug>/', views.products, name='products'),
path('<slug:brands_slug>/<slug:product_slug>/<slug:product_details>/', views.details_products, name='product_details'),
]
View:
def products(request, brands_slug, product_slug):
product = Product.objects.filter(category__slug=product_slug, category__child_category__slug=brands_slug)
context = {'product': product}
return render(request, 'shop/products.html', context=context)
def details_products(request, brands_slug, product_slug, product_details):
details = Product.objects.filter(category__child_category__slug=brands_slug, category__slug=product_slug, slug=product_details)
context = {'details': details}
return render(request, 'shop/product_details.html', context=context)
You have an issue with your datastructure.
Your Product model have multiple categories (M2M). So, when your ask for product.category you don't get a single category, but all the categories this product is. The product.category is a QuerySet.
You want to get one single slug out of a set of multiple categories, each with a different slug. This cannot work.
You have two solutions, depending on what you are trying to do.
The first one is to change the M2M relation from product to category to a ForeignKey frmo product to category. This way, product.category will give you a Category model instance instead of a Queryset.
In that case, you should rename the Product.category field to Product.categories to make it clear that you can have more than one category.
Second solution: you have to select one category from your set of categories. For example:
slug = product.category.first().slug
Beware: first() may return None if no categories are associated with this product.