Cannot use QuerySet for "Product": Use a QuerySet for "Item".

adding item to cart when click on the button it show this error
Error:

ValueError at /baskets/add-to-basket/action-chair-c4-35x35-951753
Cannot use QuerySet for "Product": Use a QuerySet for "Item".

Also the Error Highlited this line:

order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)

When i Change item = Product.objects.filter(slug=slug)
into item = Item.objects.filter(slug=slug), it shows error for the slug not an attribute of Object Item.
HTML Button

<div class="extra content">
    <a class="ui fluid button" href="{{ item.get_add_to_basket_url }}">Add To Basket</a>
    <div class="ui divider"></div>
    <a class="ui fluid button" href="{{ item.get_remove_from_basket_url }}">Remove From Basket</a>
</div>

Views.py

def ItemAddToBasketView(request, slug):
	item = Product.objects.filter(slug=slug)
	order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)
	order_qs = Order.objects.filter(account=request.user, ordered=False)
	if order_qs.exists():
		order = order_qs[0]
		if order.items.filter(item__slug=item.slug).exists():
			order_item.quantity += 1
			order_item.save()
			message.success(request, f'{item} added Quantity is Updated in Basket.')
			return redirect('Baskets:BasketDetailsUrl')
		else:
			order.items.add(order_item)
			order.save()
			message.success(request, f'{item} added to Basket.')
			return redirect('Baskets:BasketDetailsUrl')
	else:
		order = Order.objects.create(account=request.user, ordered=False, ordered_at=ordered_at)
		order.items.add(order_item)
		order.save()
		return redirect('Baskets:BasketDetailsUrl')

Models.py

class Item(models.Model):
	product = models.OneToOneField(Product, verbose_name=_('Product'), on_delete=models.CASCADE)

	def __str__(self):
		return f'{self.product}'

class OrderItem(models.Model):
	account = models.ForeignKey(Account, verbose_name=_('Order Account'), on_delete=models.CASCADE)
	item = models.ForeignKey(Item, verbose_name=_('Item'), on_delete=models.CASCADE)
	ordered = models.BooleanField(verbose_name=_('Ordered'), default=False)
	quantity = models.IntegerField(verbose_name=_('Quantity'), default=1)

	def __str__(self):
		return f'{self.item} - {self.quantity} Pieces.'

class Order(models.Model):
	order_id = models.UUIDField(verbose_name=_('Order Number'), primary_key=True, default=uuid4, unique=True, editable=False)
	account = models.ForeignKey(Account, verbose_name=_('Order Account'), on_delete=models.CASCADE)
	items = models.ManyToManyField(OrderItem, verbose_name=_('Items'))
	ordered = models.BooleanField(verbose_name=_('Ordered'), default=False)
	created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True, editable=False)
	ordered_at = models.DateTimeField(verbose_name=_('Ordered At'), auto_now=True)

	def __str__(self):
		return f'Order Id: {self.order_id} - {self.account}.'

Grateful for Clues.

The first error is (in part) as you’ve identified. You’re trying to create an OrderItem object by passing a queryset for Project as the item parameter, where item is a ForeignKey to Item, not Project.

The other part of the error here is that the .filter call returns a queryset, and not an instance. However, that item parameter in get_or_create needs to be given an instance of Item, not a queryset.

What do you think is the cause of the this error?

1 Like

Where is the SlugField defined in Item model?

1 Like

i think this error because the Item class has no attribute called slug,
but i dont know why, class Item has an attribute product which have OneToOneField to class Product.

Slug Field in Product Model and Item Model has product attribute with OneToOneField to Product Model.

great to clarify that i understood this correct.
First Part:

item = Item.objects.get(slug=slug)
order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)

to get the object from Item and send it to get_or_create Method.

Correct.

Now to address the other issue.

If you have an Item object, how do you access the related Product? (Or the reverse - if you have a Product, how do you get the related Item?)

i didn’t add Related Name, between Item and Product.
but i think to access Product from Item would be as:
Item.product_set.get()

Actually, it’s easier than that. Since it is a one-to-one relationship, no related manager is required. There’s only one related Product instance that can be retrieved per Item instance.

Also, since you have the OneToOneField defined in Item that’s a forward reference.

If you have an instance of Item named item, then item.product is the related Product instance. If you have a Product instance named product, then product.item is the reference to the related Item instance.

See One-to-one relationships | Django documentation | Django

1 Like

Great,
after i link the product into Item Instance, how to link it to the slug in my View.
is this the correct way?
as i understand this line will link product into the item but not with the slug Parameter.

item = Item.product
order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)

View:

def ItemAddToBasketView(request, slug):
	item = Item.product
	order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)
	order_qs = Order.objects.filter(account=request.user, ordered=False)
	if order_qs.exists():
		order = order_qs[0]
		if order.items.get(item__slug=item.slug).exists():
			order_item.quantity += 1
			order_item.save()
			message.success(request, f'{item} added Quantity is Updated in Basket.')
			return redirect('Baskets:BasketDetailsUrl')

You’ve got two options.

You can either write a query for Product and then retrieve the related Item, or you can write a query for Item that follows the relationship to check the slug field of the related Product.

But either way, you still need to write a query to retrieve specific object instances.

Review the docs at Making queries | Django documentation | Django

1 Like

ORM does not work this way.

Item.product is of type Product and item in OrderItem is of type Item

If you want to get Item from slug field on Product, you need to access related object reference using __ (double underscore) in filter condition.

item = Items.objects.filter(product__slug=slug).first()
order_item, created = OrderItem.objects.get_or_create(item=item, account=request.user, ordered=False)

.first() is used because, filter returns QuerySet

1 Like

Note, this is incomplete in this situation, because in the case where the slug being submitted is not valid, item will be null. If item is null, then the get_or_create call will fail.

You either want to verify that item is a valid object, or use .get and catch the error if it occurs. Either way, there needs to be guards around this block of code.

2 Likes

Exactly, one easiest way is to have get_object_or_None similar to get_object_or_404 added to the ObjectManager of the Model.

1 Like

Actually, you’d be better off using get_object_or_404 - at least at that point you would be bypassing the get_or_create call. Using get_object_or_none is no better than using the .filter().first() combination in this situation.

1 Like

@KenWhitesell @oneflydown
Thanks A lot Guys. which you a happy days.
Kind of struggling with this way of Implementation,
I changed the Implementation a little, removed the Item Class and made OrderItem Class has attribute product with ForeignKeyField to Product Class Instead of Item Class with OneToOneField into Product Class.
and i reset the DataBase and Migrations also.
now the logic is working one time only when i click add to cart it works., but when i click again it suppose to add one more product to the cart, instead it show this error

AttributeError at /baskets/add-to-basket/elegance-chair-c4-50x50-137964
'OrderItem' object has no attribute 'exists'

and Highlighted this line:

if order.items.get(product__slug=product.slug).exists():

What do you think the issue might be here?

  • On what type of object can you use the .exists function?

  • What type of object does .get return?

See the appropriate sections of QuerySet API reference | Django documentation | Django for more detailed information.

1 Like

it works on Querysets.

i got that my friend.
this line was getting an queryset not object of single item
i fixed it with Filter instead of get

if order.items.filter(product__slug=product.slug).exists():

i guess i know why it worked only first time only with .get because there was no QuerySet was only one item.