【问题标题】:Django error: ValueError at /cart/ -> The QuerySet value for an exact lookup must be limited to one result using slicingDjango 错误:/cart/ 处的 ValueError -> 精确查找的 QuerySet 值必须使用切片限制为一个结果
【发布时间】:2021-07-20 08:51:40
【问题描述】:

将图书添加到购物车时出现价值错误。它指向views.py中的for循环以获取订单。我无法想办法解决它。任何帮助表示赞赏。

bookstore-django/store/views.py",第 68 行,在购物车中 对于订单中的订单:

异常类型:ValueError at /cart/

异常值:精确查找的 QuerySet 值必须使用切片限制为一个结果。

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

【问题讨论】:

    标签: python django


    【解决方案1】:

    你的问题在这里:

    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 在这里是一个查询集,而不是一个实例。如果您希望只有一种可能的购物车,请使用.get。如果可能有多个结果,请像现在一样使用过滤器,但在订单查询中使用 __in

    改成:

    cart = Cart.objects.get(user=request.user.id, active=True)
    orders = BookOrder.objects.filter(cart=cart)
    

    carts = Cart.objects.filter(user=request.user.id, active=True)
    orders = BookOrder.objects.filter(cart__in=carts)
    

    【讨论】:

      猜你喜欢
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 2019-05-26
      相关资源
      最近更新 更多