python - Django error: ValueError at /cart/ -> The QuerySet value for an exact lookup must be limited to one result using slicing
问题描述
I am getting a value error when adding the book to the cart. It points to for loop in views.py for orders. I am not able to figure a way to solve it. Any help is appreciated.
bookstore-django/store/views.py", line 68, in cart for order in orders:
Exception Type: ValueError at /cart/
Exception Value: The QuerySet value for an exact lookup must be limited to one result using slicing.
models.py
from django.db import models
from django.db.models.query import prefetch_related_objects
from django.utils import timezone
from django.contrib.auth.models import User
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
def __str__(self):
return "%s, %s" % (self.last_name, self.first_name)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE, null=True, blank=True)
description = models.TextField()
publish_date = models.DateField(default=timezone.now)
price = models.DecimalField(decimal_places=2, max_digits=8)
stock = models.IntegerField(default=2)
class Meta:
verbose_name ='Book'
verbose_name_plural = 'Books'
db_table = 'book' #default is store_book
class Review(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
publish_date = models.DateField(default=timezone.now)
text = models.TextField()
class Cart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
active = models.BooleanField(default=True)
order_date = models.DateField(null=True)
payment_type = models.CharField(max_length=100, null=True)
payment_id = models.CharField(max_length=100, null=True)
def add_to_cart(self, book_id):
book = Book.objects.get(pk=book_id)
try:
preexisting_order = BookOrder.objects.get(book=book, cart=self)
preexisting_order.quantity += 1
preexisting_order.save()
except BookOrder.DoesNotExist:
new_order = BookOrder.objects.create(
book=book,
cart=self,
quantity = 1
)
new_order.save
def remove_from_cart(self, book_id):
book = Book.objects.get(pk=book_id)
try:
preexisting_order = BookOrder.objects.get(book=book, cart=self)
if preexisting_order.quantity > 1:
preexisting_order.quantity -= 1
preexisting_order.save()
else:
preexisting_order.delete()
except BookOrder.DoesNotExist:
pass
class BookOrder(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
quantity = models.IntegerField()
views.py
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import redirect, render
from .models import Book, BookOrder, Cart
def index(request):
context = {
}
return render(request, 'template.html', context)
def store(request):
books = Book.objects.all()
context = {
'books': books,
}
return render(request, 'base.html', context)
def book_details(request, book_id):
context = {
'book': Book.objects.get(pk=book_id),
}
return render(request, 'store/detail.html', context)
def add_to_cart(request, book_id):
if request.user.is_authenticated:
try:
book = Book.objects.get(pk=book_id)
except ObjectDoesNotExist:
pass
else:
try:
cart = Cart.objects.get(user=request.user, active=True)
except ObjectDoesNotExist:
cart = Cart.objects.create(
user=request.user
)
cart.save()
cart.add_to_cart(book_id)
return redirect('store:cart')
else:
return redirect('index')
def remove_from_cart(request, book_id):
if request.user.is_authenticated:
try:
book = Book.objects.get(pk=book_id)
except ObjectDoesNotExist:
pass
else:
cart = Cart.objects.get(user=request.user, active=True)
cart.remove_from_cart(book_id)
return redirect('cart')
else:
return redirect('index')
def cart(request):
if request.user.is_authenticated:
cart = Cart.objects.filter(user=request.user.id, active=True)
orders = BookOrder.objects.filter(cart=cart)
total = 0
count = 0
for order in orders:
total += (order.book.price * order.quantity)
count += order.quantity
context = {
'cart': orders,
'total': total,
'count': count,
}
return render(request, 'store/cart.html', context)
else:
return redirect('index')
urls.py
from django.urls import path
from . import views
app_name = 'store'
urlpatterns = [
path('', views.index, name='index' ),
path('store/', views.store, name='store' ),
path('store/<int:book_id>', views.book_details, name='book_details'),
path('add/<int:book_id>', views.add_to_cart, name='add_to_cart'),
path('remove/<int:book_id>', views.remove_from_cart, name='remove_from_cart'),
path('cart/', views.cart, name='cart'),
]
cart.html
{% block body %}
<div class="col-md-8 col-md-offset-2 col-sm-12 maincontent col-center">
<div style="text-align:center;text-decoration:underline"><h3>Your Cart</h3></div>
<div class="cart_container">
{% for item in cart %}
<div class="cart_item">
<div class="cart_listing">
<span class="title">{{ item.book.title }}</span> by {{ item.book.author.first_name }} {{ item.book.author.last_name }}
</div>
<div class="cart_price">
<span class="cart_quantity">{{ item.quantity }} x $ <span class="cart_value">{{ item.book.price }}</span></span>
Quantity: <a href="{% url 'store:add_to_cart' book.id %}">[+]</a> /
<a href="{ url 'store:remove_from_cart' item.book.id %}">[-]</a>
</div>
</div>
{% empty %}
<div>
There are no items in your cart.
</div>
{% endfor %}
<div class="cart_total">
<h4> Total: $<span class="cart_value">{{ total }}</span></h4>
</div>
</div>
</div>
</div>
{% endblock %}
base.html
{% block body %}
<div class="col-md-8 col-md-offset-2 col-sm-12 maincontent col-center" >
<div style="text-align:center"><h3>Welcome to our store!</h3></div>
{% for book in books%}
<div class="storefront_book_display">
<a href="{% url 'store:book_details' book.id %}">
<img src="{% static 'base/img/empty_cover.jpg' %}">
<span class="storefront_book_title">{{ book.title }}</span>
<span class="storefront_book_author">{{ book.author }}</span>
</a>
<span class="storefront_add_to_cart">
<a href="{% url 'store:add_to_cart' book.id %}">Add to cart</a>
</span>
</div>
{% endfor %}
</div>
{% endblock %}
解决方案
Your problem is here:
cart = Cart.objects.filter(user=request.user.id, active=True) # this is a queryset
orders = BookOrder.objects.filter(cart=cart) # this is the exact lookup mentioned
cart
is a queryset here, not an instance. If you expect just one possible cart use .get
. If there is a chance of having multiple results use filter like you are doing now but use __in
on the orders query.
Change it to:
cart = Cart.objects.get(user=request.user.id, active=True)
orders = BookOrder.objects.filter(cart=cart)
or
carts = Cart.objects.filter(user=request.user.id, active=True)
orders = BookOrder.objects.filter(cart__in=carts)
推荐阅读
- c# - 有没有办法访问 SQL Server Express 的 Windows 身份验证的用户 ID?
- ios - Flutter 医生报告通过 Jenkins 运行时未安装 CocoaPods,但通过终端运行正常
- multithreading - 如何访问 Akka Actor 系统的底层线程池/分叉连接池
- python - 从已运行事件循环的同步函数运行异步代码
- postgresql - 服务器超时连接到 ElephantSQL
- javascript - 使用 AJAX 从 VB 文件请求 webmethod 信息时出现问题
- zabbix - Zabbix - 是否可以根据收到的 http 响应代码调用外部 api
- javascript - 解决 web-dev-server pixi.js "import does not provide an export named 'default'" 冲突
- python - 如何返回我的输出而不是打印?
- angular - Angular,2 个主题,combineLatest 不起作用