I am sorting products by categories. When I am viewing product's details, the program outputs following error:
MultipleObjectsReturned at /default/1/ get() returned more than one Product -- it returned 2! Users/artemiikhristich/PycharmProjects/Eshop-original/store/views.py, line 114, in product_detail product = get_object_or_404(Product, slug=slug)
product.html
This template is used for viewing product details
% extends "store/main.html" %}
{% block content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tutorial</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<!-- CSS -->
<link href="static/css/style.css" rel="stylesheet">
<meta name="robots" content="noindex,follow" />
</head>
<body>
<main >
<!-- Left Column / Headphones Image -->
<!-- Right Column -->
<div >
<!-- Product Description -->
<div >
<span></span>
<h1>{{product.name}}</h1>
<div >
<img data-image="black" src="{{ product.imageURL }}">
</div>
<p>"{{product.description}}"</p>
</div>
<!-- Product Configuration -->
</div>
<!-- Product Pricing -->
<div >
<button data-product="{{product.id}}" data-action="add" >Add to Cart</button>
<div >
<a href="#">How to take the measurements</a>
</div>
</div>
</div>
</main>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" charset="utf-8"></script>
<script src="static/js/script.js" charset="utf-8"></script>
</body>
</html>
{% endblock %}
views.py
Here I have views for product_detail and category_detail
class ProductList(ListView):
model = Product
def product_detail(request, category_slug, slug):
product = get_object_or_404(Product, slug=slug)
context = {
'product': product
}
return render(request, 'store/product.html', context)
def category_detail(request, slug):
category = get_object_or_404(Category, slug=slug)
products = category.products.all()
context = {
'category': category,
'products': products
}
return render(request, 'store/category_detail.html', context)
enter code here
urls.py
from django.urls import path
from . import views
from .views import product_detail, category_detail
urlpatterns = [
# Leave as empty string for base url
path('', views.store, name="store"),
path('cart/', views.cart, name="cart"),
path('checkout/', views.checkout, name="checkout"),
path('update_item/', views.updateItem, name="update_item"),
path('process_order/', views.processOrder, name="process_order"),
path('<slug:category_slug>/<slug:slug>/', product_detail, name='product-detail'),
path('<slug:slug>/', category_detail, name='category_detail')
]
models.py
Here I am linking category and product with foreign key
class Category(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, default=1)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.title
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE, default=1)
name = models.CharField(max_length=200)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
description = models.TextField(null=True, blank=True)
slug = models.SlugField(max_length=255, default=1)
def __str__(self):
return self.name
@property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
CodePudding user response:
Well your challenge comes from you using get_object_or_404 it would be better to do something like this for your detail view:
def product_detail(request, category_slug, slug):
product = Product.objects.get(slug=slug)
context = {
'product': product
}
return render(request, 'store/product.html', context)
CodePudding user response:
The issue was with the slug field. Previously, in models.py I had:
slug = models.SlugField(max_length=255, default=1)
I have slug field for Product and Category models. Slug is like a unique ID for the product. Previously I said that every time the product is created, the default=1
. However, This was not unique as you can imagine. My solution:
slug = models.SlugField(max_length=255, unique=True, default=uuid.uuid1)
I am using unique=True
with Universal Unique Identifier library
I hope this helps. Feel free to leave any comments