Search code examples
djangodjango-urlsdjango-url-reverse

Removed model instances and error "NoReversematch"


I am encountering the error message similar to this post here.

However, I received this message only after I have done the following steps to my django model instances, particularly in the admin.

I have a model, called "Product". In admin, I create a few instances of this Product, each with an "id" field. So, I have 5 products, each with "id" "1", "2", "3", "4" and "5".

I have an html template that displays the list of all "products", with a url link to each product given by this:

class Product(models.Model)
   ...
   def get_absolute_url(self):
        return reverse('catalog:product_detail',
                       args=[self.id, self.slug])

Here is that part of the template:

<a href="{{ product.get_absolute_url }}"> </a>

Clicking this url brings to a product detail view as following (in views.py):

def product_detail(request, id, slug):
    product = get_object_or_404(Product,
                                id=id,
                                slug=slug)    

    return render(request,
                  'catalog/product/detail.html',
                  {'product': product,})

I also created a context processor to keep track of the products created in all templates in this website in a context_processors.py.

Now, when I delete the first few products in admin (product "1", "2", "3"), and at the same time, create new products in admin (add "6", "7", "8" and "9"), when I re-render the template, I got this "NoReverseMatch" error.

I am guessing that since the products get removed in admin, but the context process still keeps a record of that products, the template could not find the reverse url anymore. How do I "reset" this situation (i.e. reset all my products or the context processors)?


Solution

  • i guess you have an app called catalog in which you defined Product model

    i think, you don't even need the id since slug have to be unique obviously (in Product model)

    class Product(models.Model):
        """Model to store Products."""
    
        slug = models.SlugField(_('slug'), max_length=255,
            unique=True, null=True, blank=True,
            help_text=_(
                'If blank, the slug will be generated automatically '
                'from the given name.'
            )
        )
    
    
        name = models.CharField(_('name'), max_length=255,
            unique=True,
            help_text=_('The title of the product.')
        )
    
        [..]
    
        def save(self, *args, **kwargs):
            if not self.slug:
                self.slug = slugify(self.name)
            super(Product, self).save(*args, **kwargs)
    
    

    in your function

    def product_detail(request, slug):
        product = get_object_or_404(Product, slug=slug)
    
        return render(request,
                      'catalog/product/detail.html',
                      {'product': product,})
    

    you can define your route like

    app_name = 'catalog'
    urlpatterns = [
    ..
        path('products/<slug:slug>', views.product_detail, name='product_detail'),
    ..
    ]
    

    and then in your template call the url

    <a href="{% url 'catalog:product_detail' slug=product.slug %}"> </a>