Hi everyone,
I have the following view:
def update_cart(request, id):
cart = Cart.objects.all()
product = Product.objects.get(pk=id)
cart.products.add(product)
return HttpResponseRedirect(reverse("update_cart_url", args=(product.id)))
And URL pattern in my project level urls.py (after importing update_cart from carts.views):
path('cart/<int:product.id>/', update_cart, name="update_cart_url")
Which are called in a template:
<h3>{{ product.name}}<a href=" {% url 'update_cart_url' product.id %}">Add to Cart</a></h3>
When rendering the template, I receive the following error:
NoReverseMatch at /webCart/detail/6/
Reverse for 'update_cart_url' with arguments '(6,)' not found. 1 pattern(s) tried: ['cart/<int:product\\.id>/$']
Note that the argument 6 above correctly matches the id of the item that the template was attempting to render.
There are lots of resources online in respect to this exception, and reading through them I believe I narrowed down my problem to several possibilities:
-
I am using args when I should be using kwargs or vice versa
-
I am attempting to reverse a URL by using path instead of url in urls.py
-
Should the url pattern be defined within the app directory rather than the project directory?
Does anyone have any ideas?
Dots arenât supported in url pattern variable names. Use an underscore instead and your problem should be solved.
1 Like
I believe the issue may be here:
The url just contains an integer, which you can then use as the parameter being passed to your view to retrieve the specific object to which it refers.
try:
path('cart/<int:id>/', update_cart, name="update_cart_url")
Also, and Iâm not sure if it makes a difference here, but:
I believe args needs to be an iterable. This is one of those python gotchas that gets me all-too-often. Try either:
return HttpResponseRedirect(reverse("update_cart_url", args=(product.id,)))
or
return HttpResponseRedirect(reverse("update_cart_url", args=[product.id]))
In the first example, adding the trailing comma forces args to be a tuple and not just the singular value. In the second, youâre definitely passing a list - both of which are iterables.
Ken
1 Like
Thank you both, this is super helpful. The he tutorial is helpful as well.
So Django wasnât parsing your URL attempt correctly - it would see the dot in <int:product.id>
and âskip overâ trying to convert it. It therefore didnât hit its built-in warning that youâve typed something thatâs not a valid identifier.
Iâve made a ticket and PR to try fix this for future versions in Django, so others wonât hit the same problem again
@KenWhitesell was right about the brackets for the tuple as well. I prefer using lists wherever possible for this reason. See my post.
1 Like