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!
models:
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)
views:
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})
template:
{% 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 %}
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
Traceback:
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