I have a cart view where I'm trying to check if the products added to the cart have even one item in the list that has product.availability
set to False and work accordingly in Template, the problem is with accessing the product availability in cart object list, So how do I check the availability of products that people added to cart?
P.S I shortened the code for utils, I'll add more if needed for understanding
Model
class Product(models.Model):
availability = models.BooleanField()
Utils
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
items = []
for i in cart:
try:
product = Product.objects.get(id=i)
item = {
'product':{
'id':product.id,
'name':product.name,
'final_price':product.final_price,
'image_URL':product.image_URL,
'availability':product.availability,
},
'quantity':cart[i]["quantity"],
'get_total':total,
}
items.append(item)
except:
pass
return {"items": items}
def cartData(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
cookieData = cookieCart(request)
items = cookieData['items']
return {'items':items}
Views
def cart(request):
data = cartData(request)
#products added to cart
items = data['items']
#Checking if even one product added to cart has availability set to False
available = all(x.availability for x in items)
context = {'items': items, 'available': available}
Template
<p>{{items.product.name}}</p>
{% if available %}
<a href="#">Checkout</a>
{% else %}
<p>Out of stock</p>
{% endif %}
Traceback
Traceback (most recent call last):
File "D:\test\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "D:\test\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\test\shop\views.py", line 101, in cart
available = all(x.availability for x in items)
File "D:\test\shop\views.py", line 101, in <genexpr>
available = all(x.availability for x in items)
Exception Type: AttributeError at /shop/cart
Exception Value: 'dict' object has no attribute 'availability'
CodePudding user response:
Its quite simple, in the cookieCart function you are appending to the items list a dictionary, not a Product object.
Change to:
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
items = []
for i in cart:
try:
product = Product.objects.get(id=i)
items.append(product)
except:
pass
return {"items": items}
CodePudding user response:
Instead of creating an ad-hoc dict that does have the necessary availability
attribute, you should simply return a QuerySet
of Product
objects after filtering products by IDs:
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
return {"items": Product.objects.filter(id__in=cart)}
CodePudding user response:
This part is creating issue
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
items = []
for i in cart:
try:
product = Product.objects.get(id=i)
item = {
'product':{
'id':product.id,
'name':product.name,
'final_price':product.final_price,
'image_URL':product.image_URL,
'availability':product.availability,
},
}
items.append(item)
except:
pass
return {"items": items} # here your items is like this {"items": [{'product':{'id':product.id,'name':product.name,'final_price':product.final_price,'image_URL':product.image_URL,'availability':product.availability}}]}
Since error is suggesting that you picked item from COOKIES
Now since you are looping as all(x.availability for x in items)
x will look like {price: {...}}
which is dict object thatswhy it is saying that dict object has no attribute availability
For resolving this issue use SimpleNameSpace
like this
from types import SimpleNamespace
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
items = []
for i in cart:
try:
product = Product.objects.get(id=i)
item = SimpleNamespace(**{
'id':product.id,
'name':product.name,
'final_price':product.final_price,
'image_URL':product.image_URL,
'availability':product.availability,
})
items.append(item)
except:
pass
return {"items": items}
For optimised way you can check @blhsing solution