Home > Software design >  Django Error: 'dict' object has no attribute 'availability'
Django Error: 'dict' object has no attribute 'availability'

Time:10-21

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

  • Related