Manko
Manko

Reputation: 91

NoReverseMatch with 2 slug parameters in django

i have the following problem.

I want to have a detailview on this url: 127.0.0.1:8000/<category-name>/<product-name> (category-name and product-name is slug field.) right from the index page. Please help :(

My error:

NoReverseMatch at /products/ Reverse for 'ProductDetail' with arguments '('new-things', 'flower-pot')' not found. 1 pattern(s) tried: ['products\\/\\<slug\\:category\\.slug\\>\\/\\<slug\\:product\\.slug\\>$']

my (relevant part) index.html:

{% for p in Product %}
  <a href="{% url 'product:ProductDetail' p.category.slug p.slug %}">{{ p.name}}</a>
{% endfor %}

my (relevant part) urls.py:

from .models import *

app_name = 'product'
urlpatterns = [
    path('product/<slug:category.slug>/<slug:product.slug>', views.ProductDetailView.as_view(), name="ProductDetail"),
]

and (relevant part) my models.py:

    class Product(models.Model):
        name = models.CharField(max_length=100)
        description = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
        slug = models.SlugField(blank=True, null=True)

            def save(self, *args, **kwargs):
                if not self.id:
                    # Newly created object, so set slug
                    self.slug = slugify(self.name)

                super(Product, self).save(*args, **kwargs)

            def __str__(self):
                return self.name


class Category(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    slug = models.SlugField(blank=True, null=True)

        def save(self, *args, **kwargs):
            if not self.id:
                # Newly created object, so set slug
                self.slug = slugify(self.name)

            super(Category, self).save(*args, **kwargs)

        def __str__(self):
            return self.name

Upvotes: 0

Views: 97

Answers (2)

Jrog
Jrog

Reputation: 1527

First, Product model does not have category. Append ForeignKey to your Product model.

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    slug = models.SlugField(blank=True, null=True)
    category = models.ForeignKey('Category', on_delete=models.CASCADE) # change on_delete what you want.

        def save(self, *args, **kwargs):
            if not self.id:
                # Newly created object, so set slug
                self.slug = slugify(self.name)

            super(Product, self).save(*args, **kwargs)

        def __str__(self):
            return self.name

Second. Your url settings is wrong. You can not use . in url param. Change your code.

urlpatterns = [
    path('product/<slug:category_slug>/<slug:product_slug>', views.ProductDetailView.as_view(), name="ProductDetail"),
]

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599628

It doesn't make sense to use dots in the parameter names. Use underscores:

path('product/<slug:category_slug>/<slug:product_slug>', views.ProductDetailView.as_view(), name="ProductDetail"),

However, this still won't really work as you are trying to refer to a category via a product; but your models don't have any relationship between Product and Category. I assume you need to have a ForeignKey from Product to Category.

Upvotes: 1

Related Questions