Django添加到购物车和购物车视图错误
当我通过scan_to_cart视图向购物车中添加1个对象并想要添加第二个对象时,出现 NoneType对象不可迭代错误。当我实际上想要查看购物车中的物品时,也会遇到相同的错误。
我找不到解决方案的常见问题...是我处理的python版本,还是有逻辑或代码错误?
I get a 'NoneType' object is not iterable error when I add 1 object to the cart via the scan_to_cart view and want to add a second object. Also I get the same error when I want to view my cart when there are actually objects in it. I could not find a common problem with a solution... Is the python version I work with the issue, or is there a logic or code error?
感谢您提出建议/建议!
Thanks in advance for 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中的
TypeError /
Error: TypeError at /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中,此处:
In Cart.new_or_get, here:
if qs.count() == 1:
# ...
else:
# ...
return cart_obj, new_obj
如果有购物车,则不返回任何内容,因此该函数最终返回 None
,这确实是不可迭代的,因此在尝试取消定位时k您在此处看到的结果:
if a cart exists you do not return anything, so the function ends up returning None
, which is indeed not iterable, so when trying to unpack the result in your view here:
cart_obj, new_obj = Cart.objects.new_or_get(request)
您会遇到此异常。
TL; DR:您应该取消缩排
TL;DR: you should unindent the return statement so it executed for both branches.
这就是说,您的 Cart.new_or_get
方法是错误的-模型代码不应依赖于请求,会话等。所有这些代码都应该存在于您的视图中(如果这是唯一的使用位置)或作为实用工具功能(或在充当模型代理的实用工具类中)。
This being said, your Cart.new_or_get
method is plain wrong - model code should not depend on the request, session etc. All this code should live either in your view (if that's the only place it's used) or as an utility function (or in an utility class acting as proxy over the model).