execution
execution

Reputation: 13

DJANGO: Product matching query does not exist

Error message

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}"

Database Database2

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

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

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

Related Questions