Reputation: 13
I don’t understand what’s the matter. I do everything exactly according to the courses, but knocks out an error: Request URL: http://127.0.0.1:8000/products/basket-add/12/ Django Version: 3.2.4 Exception Type: DoesNotExist Exception Value: Product matching query does not exist.
Add object:
def basket_add(request, product_id):
current_page = request.META.get('HTTP_REFERER')
product = Product.objects.get(id=product_id)
baskets = Basket.objects.filter(user=request.user, product=product)
if not baskets.exists():
Basket.objects.create(user=request.user, product=product, quantity=1)
return HttpResponsePermanentRedirect(current_page)
else:
basket = baskets.first()
basket.quantity += 1
basket.save()
return HttpResponsePermanentRedirect(current_page)
Delete:
def basket_delete(request, id):
basket = Basket.objects.get(id=id)
basket.delete()
return HttpResponsePermanentRedirect(request.META.get('HTTP_REFERER'))
template:
<a href="{% url 'products:basket_delete' basket.id %}" style="text-decoration: none; color: gray;">
<i class="far fa-trash-alt"></i>
</a>
URLs:
from django.urls import path
from products.views import products, basket_add, basket_delete
app_name = 'products'
urlpatterns = [
path('', products, name="index"),
path('basket-add/<int:product_id>/', basket_add, name="basket_add"),
path('basket-add/<int:id>/', basket_delete, name="basket_delete"),
]
Models:
from django.db import models
from users.models import User
class ProductCategory(models.Model):
name = models.CharField(max_length=64, unique=True)
description = models.TextField(blank=True)
class Meta:
verbose_name_plural = "Product Categories"
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=256)
image = models.ImageField(upload_to='products_images', blank=True)
description = models.TextField(blank=True)
short_description = models.CharField(max_length=64, blank=True)
price = models.DecimalField(max_digits=8, decimal_places=2, default=0)
quantity = models.PositiveIntegerField(default=0)
category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE)
def __str__(self):
return f"{self.name} ({self.category.name})"
class Basket(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=0)
created_timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Basket for {self.user.username} | Product {self.product.name}"
On version 3.2.4, Django throws this error, on 2.8 it throws it to another page (and not the current one) and sometimes adds a new item to the cart and never removes it from it. I saw the advice to use get_or_404, but it won't fix the error.
Upvotes: 1
Views: 3403
Reputation: 476709
You have two url patterns that completely overlap. This means that it will trigger the first view in case you call that view.
You thus should make url patterns that do not completely overlap, and preferrably do not overlap at all, so:
urlpatterns = [
path('', products, name="index"),
path('basket-add/<int:product_id>/', basket_add, name="basket_add"),
path('basket-delete/<int:id>/', basket_delete, name="basket_delete")
]
so for the second path, we replaced basket-add/
with basket-delete/
.
Note: Section 9 of the HTTP protocol specifies that requests like GET and HEAD should not have side-effects, so you should not change entities with such requests. Normally POST, PUT, PATCH, and DELETE requests are used for this. In that case you make a small
<form>
that will trigger a POST request, or you use some AJAX calls.
Upvotes: 2