【问题标题】:Adding Items To Shopping Cart Django Python将商品添加到购物车 Django Python
【发布时间】:2016-03-22 18:33:50
【问题描述】:

编辑 当我点击添加到购物车时,这是终端的输出

[22/Mar/2016 07:07:44] "GET /store/add/7 HTTP/1.1" 302 0
[22/Mar/2016 07:07:44] "GET /store/ HTTP/1.1" 200 4888

我有两个功能,一个将项目添加到购物车,一个删除。

我认为问题在于我的 URL 请求没有正确形成。因此,我会感谢比我更有经验的人向我解释预期的 URL 应该是什么。

我正在这样创建我的 URL,

url(r'^add/(\d+)', views.add_to_cart, name='add_to_cart'),  
    url(r'^remove/(\d+)', views.remove_from_cart, name='remove_from_cart'),
    url(r'^cart/', views.cart, name='cart'),

将商品添加到购物车的链接位于 base.html 文件中,如下所示,

  {% if request.user.is_authenticated %}
         <span class="storefront_add_to_cart">
             <a href="{% url 'add_to_cart' book.id %}">[Add to Cart]</a>
         </span>
         {% endif %}

因此,当您在购物车中添加或删除商品时,它会调用相应的函数。

Views.py

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('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')

当我点击添加到购物车时,网址看起来像这样(这给了我错误)

http://localhost:8000/store/add/4

当我点击从购物车中删除时,网址看起来像这样,但我没有收到任何错误。 (购物车中的商品会保留,不会移除。)

http://localhost:8000/store/cart/%7B%20url%20'remove_from_cart'%20item.book.id%20%%7D

如果有帮助的话,models.py 中的各个模型

class Cart(models.Model):
    user = models.ForeignKey(User)
    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 __unicode__(self): 
            return "%s" % (self.user)

    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 __unicode__(self):
                return "%s" % (self.book_id)


    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

【问题讨论】:

  • 如果用户未通过身份验证,您的代码不会返回任何内容。这就是导致错误的原因
  • 我已登录。您是说即使我已登录也是问题所在。删除时的 url 看起来是否正确?
  • 如果是这样,那么您遇到了 ObjectDoesNotExist 异常。在 django 中,视图总是必须返回一些响应。因此,请确保您遵循该标准
  • 感谢您的回复。你介意给我一些关于如何解决这个问题的建议吗?
  • 对于初学者,您可以在代码中添加打印语句并检查您遇到异常的位置

标签: python django


【解决方案1】:

让我们一次解决这个问题。

首先,您需要使用login_required decorator;您也不应该接受将无效书籍添加到购物车(您当前正在数据库级别检查,并且不会向客户显示此错误)。

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404

@login_required
def add_to_cart(request,book_id):
    book = get_object_or_404(Book, pk=book_id)
    cart,created = Cart.objects.get_or_create(user=request.user, active=True)
    cart.add_to_cart(book_id)
    return redirect('cart')

接下来,您需要修复生成链接以从购物车中删除商品的 模板。您的链接应该是:

<a href="{% url 'remove_from_cart' args=(item.book.id,) %}">Remove item</a>

在您的模型中,您有两个 __unicode__ 方法,我认为这是复制粘贴中的错误,否则您需要删除第二个,因为它已缩进到 add_to_cart 方法中,所以无论如何都不起作用,来自您的models.py

无论如何,您不需要该方法,您应该将整个逻辑保留在您的视图中。这是修改后的方法:

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
from django.contrib import messages

from .models import Cart, BookOrder, Book

@login_required
def add_to_cart(request,book_id):
    book = get_object_or_404(Book, pk=book_id)
    cart,created = Cart.objects.get_or_create(user=request.user, active=True)
    order,created = BookOrder.objects.get_or_create(book=book,cart=cart)
    order.quantity += 1
    order.save()
    messages.success(request, "Cart updated!")
    return redirect('cart')

【讨论】:

  • 首先非常感谢您如此友善并花时间帮助我。我为我的无知道歉。您是否建议我完全从模型中删除 add_to_cart def 并用您的 add_to_cart 完全替换视图中的方法?我尝试在视图中替换它并离开模型。并删除模型和视图,然后在视图中添加您的方法。两种方式我都会收到 500 错误,并且 /store/add/4 NOT NULL 约束处​​的 IntegrityError 失败:store_bookorder.quantity
  • 这是因为模型中的数量没有默认值;所以当你运行get_or_create 并且不提供数量值时,你会得到这个异常。解决这个问题的最简单方法是在你的 models.py 中给数量一个默认值。
  • 非常感谢我让 add_to_cart 工作。我似乎无法让 remove_from_cart 工作。保持方法相同并添加您提供的链接不断给我语法错误,但我没有看到错误。 args=(item.book.id) 我们能不能像重写 add 函数一样重写视图中的 remove 函数?
  • 当然可以,但是 StackOverflow 不是代码编写服务;尽你最大的努力,如果你遇到问题 - 请打开一个新问题。如果解决方案适合您,请务必先关闭此问题by accepting an answer
【解决方案2】:

您应该检查book_id 的类型。它将是“unicode”。因此比较 Book.objects.get(pk=book_id) 将不起作用。

您需要将其类型转换为整数。

使用:book_id = int(book_id)

之前

book = Book.objects.get(pk=book_id)

希望对你有帮助。

【讨论】:

  • URL 正则表达式指定\d+。所以我猜它默认被认为是int?
  • 这实际上是有道理的,谢谢。那我会在模型中这样做吗?还是在这个观点?所以代替它做 book = int(book_id)
  • @wuno:你自己不能这样做
  • @AswinMurugesh:尽管 URL 正则表达式指定 \d+,但数据类型仍将是 unicode。你应该自己检查一下。我在发布答案之前对其进行了测试。
  • 但如果这是问题所在,那么为什么我的 url 仍然得到 int?在我的问题中,您可以看到 url 的值是 4。我在 add_to_cart 的模型中返回 book_id,def __unicode__(self): return "%s" % (self.book_id) - 它在我上面的问题中
【解决方案3】:

我认为问题在于这里的缩进。

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('cart')
    else:
        return redirect('index')

【讨论】:

  • 我的 linter 确实给了我一个错误。但事实并非如此。我得到的错误是变量 book 已分配但从未使用过。在这条线上 book = Book.objects.get(pk = book_id) |我不明白为什么,因为我正在学习 Udemy 的教程,这对他有用。
  • 你可以忽略这个关于未使用变量的错误,因为你实际上需要ObjectDoesnotExist这个视图的逻辑异常。
猜你喜欢
  • 1970-01-01
  • 2016-12-19
  • 2020-01-14
  • 2015-03-31
  • 2018-04-10
  • 1970-01-01
  • 2017-02-07
相关资源
最近更新 更多