Django 添加到购物车和购物车视图错误

Django add to cart and cart view error

当我通过 scan_to_cart 视图将 1 个对象添加到购物车并想添加第二个对象时,出现 'NoneType' 对象不可迭代错误。当我想查看我的购物车时,我也会遇到同样的错误,而实际上其中有物品。 我找不到解决方案的常见问题...我处理的 python 版本是这个问题,还是存在逻辑或代码错误?

提前感谢 suggestions/advice!

型号:

from manageinv.models import Child

User = settings.AUTH_USER_MODEL

class CartManager(models.Manager):  
    def new_or_get(self, request):
        cart_id = request.session.get("cart_id", None)
        qs = self.get_queryset().filter(id=cart_id)
        if qs.count() == 1:
            new_obj = False
            cart_obj = qs.first()
            if request.user.is_authenticated() and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
        else:
            cart_obj = Cart.objects.new(user=request.user)
            new_obj = True
            request.session['cart_id'] = cart_obj.id
            return cart_obj, new_obj

    def new(self, user=None):
        user_obj = None
        if user is not None:
            if user.is_authenticated():
                user_obj = user
        return self.model.objects.create(user=user_obj)


class Cart(models.Model):
    user        = models.ForeignKey(User, null=True, blank=True)
    products    = models.ManyToManyField(Child, blank=True)
    subtotal    = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
    total       = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
    updated     = models.DateTimeField(auto_now=True)
    timestamp   = models.DateTimeField(auto_now_add=True)

    objects = CartManager()

    def __str__(self):
        return str(self.id)


def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
    if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
        products = instance.products.all()
        total = 0 
        for x in products:
            total += x.retail_price
        if instance.subtotal != total:
            instance.subtotal = total
            instance.save()

m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through)

def pre_save_cart_receiver(sender, instance, *args, **kwargs):
    instance.total = instance.subtotal

pre_save.connect(pre_save_cart_receiver, sender=Cart)   

观看次数:

def cart_home(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
products = cart_obj.products.all()
return render(request, 'stockscan/scan_session.html', {"cart":
cart_obj})

def scan_to_cart(request):
    form = forms.ScanSessionForm()
    if request.method == 'POST':
        product = None
        barcode = request.POST.get('barcode_input')
        queryset = Child.objects.filter(product_id_code=barcode)
        if queryset.exists():
            try:
                # the queryset is already filtered by the barcode
                # now we apply an extra filter to check if this user has the product
                product = queryset.get(user=request.user)
            except Child.DoesNotExist:
                # here we are sure this product exists, but this user doesnt have it in the stock.
                messages.error(request, 'I can\'t find any inventory with this barcode')
        else:
            # here we know this product doesnt exist
            messages.error(request, 'I can\'t find any inventory with this barcode')
        if product is not None:
            form = forms.ScanSessionForm(request.POST, instance=product)
            if form.is_valid():
                #####
                #ADD TO CART
                print(product.id)
                product_obj = product.id
                cart_obj, new_obj = Cart.objects.new_or_get(request)
                products = cart_obj.products.all()
                cart_obj.products.add(product_obj)
                #####
                messages.success(request, '%s - %s was successfully added to cart' % (product.product_name, product.sku))   
                return HttpResponseRedirect('/scan/stock/')
    else:
        form = forms.ScanSessionForm()
    return render(request, 'stockscan/scan_to_cart.html', {'form': form})

模板:

{% if cart.products.exists %}
<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Product Name</th>
      <th scope="col">Product Price</th>
    </tr>
  </thead>
  <tbody>
    {% for product in cart.products.all %}
    <tr>
      <th scope="row">{{ forloop.counter }}</th>
      <td>{{ product.product_name }} <small><a href="#">Remove</a></small></td>
      <td>{{ product.retail_price }}</td>
    </tr>
    {% endfor %}
    <tr>
      <td colspan="2"></td>
      <td><b>Subtotal</b>  {{ cart.subtotal }}</td>
    </tr>
    <tr>
      <td colspan="2"></td>
      <td><b>Total</b> {{ cart.total }}</td>
    </tr>
  </tbody>
</table>
{% else %}
Cart is empty
<p>
{% endif %}

错误: /scan/stock/

处出现类型错误
'NoneType' object is not iterable

Request Method:     POST
Request URL:    http://localhost:8000/scan/stock/
Django Version:     1.11
Exception Type:     TypeError
Exception Value:    

'NoneType' object is not iterable

Exception Location:     /Users/sp_env/stockpilot/src/stockscan/views.py in scan_to_cart, line 41
Python Executable:  /Users/sp_env/bin/python

回溯:

Environment:


Request Method: POST
Request URL: http://localhost:8000/scan/stock/

Django Version: 1.11
Python Version: 2.7.10
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'mathfilters',
 'bootstrapform',
 'colorfield',
 'gunicorn',
 'crispy_forms',
 'storages',
 'manageinv',
 'categories',
 'stockscan',
 'orderstock',
 'accounts']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

    File "/Users/sp_env/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
      41.             response = get_response(request)

    File "/Users/sp_env/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
      187.                 response = self.process_exception_by_middleware(e, request)

    File "/Users/sp_env/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
      185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

    File "/Users/sp_env/stockpilot/src/stockscan/views.py" in scan_to_cart
      41.               cart_obj, new_obj = Cart.objects.new_or_get(request)

    Exception Type: TypeError at /scan/stock/
    Exception Value: 'NoneType' object is not iterable

在Cart.new_or_get,这里:

if qs.count() == 1:
   # ...
else:
   # ...
   return cart_obj, new_obj

如果购物车存在,你不会 return 任何东西,所以函数最终 returning None,这确实是不可迭代的,所以当试图解压结果时您在这里的看法:

 cart_obj, new_obj = Cart.objects.new_or_get(request)

你得到这个异常。

TL;DR:您应该取消缩进 return 语句,以便它对两个分支都执行。

也就是说,您的 Cart.new_or_get 方法完全错误 - 模型代码不应依赖于请求、会话等。所有这些代码都应该存在于您的视图中(如果那是唯一使用它的地方)或作为效用函数(或作为模型代理的效用 class)。