AttributeError: 'QuerySet' object has no attribute 'product' ERROR - python

Hi I'm building a Webshop with a cart and checkout function. Now I'm trying to add the products and their quantity to an Email form which I want to send to an email obviously but I don't know how I could get the item.name or the item.quantity without getting an error as shown below.
I have the following models:
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False) # Nicht nötig
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=False)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
total = self.product.price * self.quantity
return total
So I'm trying to get the product name and quantity from an Query set. But I get an error as described in the title
AttributeError: 'QuerySet' object has no attribute 'product'.
I'm trying to append the product name and quantity a customer has selected to a message variable which will be send to an email with sendmail().
This is my view:
#login_required(login_url='login')
def checkout(request):
if request.method == "POST":
message_name = request.POST['message-name']
message_email = request.POST['message-email']
message = request.POST['message']
message_to_send = str(message)
# send an email
send_mail(
'message from ' + message_name, # subject
message_to_send, # message
message_email, # from email
['jeampo#outlook.de'], # To Email
)
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()
cartItems = order.get_cart_items
print(items.product.name)
print(items.quantity)
context = {'items': items, 'order': order, 'cartItems': cartItems}
return render(request, 'store/checkout.html', context)
Thank you for any help.

You are calling items.product.name in your print statement, but items is a set of objects not just a single object.
You can fix this by using the following code in your views.py in place of print(items.product.name)
for item in items:
print(item.product.name)
You can also reference this directly in your template, by using the {% for %} code.
Example:
Inside your template.html
{% for item in items %}
<h1>{{item.product.name}}</h1>
{% endfor %}

Related

AttributeError: 'Order' object has no attribute 'shipping'

Learning Django with Tutorial.
In the end of lesson I have error:
AttributeError: 'Order' object has no attribute 'shipping'.
I can't understand what's wrong.
Error in PyCharm Terminal
I understand that Order must have shipping attribute, but cant find where exactly looking that.
Sorry for bad english.
My project files:
checkout.html
from django.db import models
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_addet = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
total = self.product.price * self.quantity
return total
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
address = models.CharField(max_length=200, null=False)
city = models.CharField(max_length=200, null=False)
state = models.CharField(max_length=200, null=False)
zipcode = models.CharField(max_length=200, null=False)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
views.py
from django.shortcuts import render
from django.http import JsonResponse
import json
import datetime
from .models import *
def store(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()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0, 'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
products = Product.objects.all()
context = {'products':products, 'cartItems':cartItems}
return render(request, 'store/store.html', context)
def cart(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()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0, 'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
context = {'items':items, 'order':order, 'cartItems':cartItems}
return render(request, 'store/cart.html', context)
def checkout(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()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0, 'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
context = {'items':items, 'order':order, 'cartItems':cartItems}
return render(request, 'store/checkout.html', context)
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
print('Action', action)
print('productId', productId)
customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer, complete=False)
orderItem, created = OrderItem.objects.get_or_create(order=order, product=product)
if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)
orderItem.save()
if orderItem.quantity <=0:
orderItem.delete()
return JsonResponse('Item was added', safe=False)
def processOrder(request):
transaction_id = datetime.datetime.now().timestamp()
data = json.loads(request.body)
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
total = float(data['form']['total'])
order.transaction_id = transaction_id
if total == float(order.get_cart_total):
order.complete = True
order.save()
if order.shipping == True:
ShippingAddress.objects.create(
customer=customer,
order=order,
address=data['shipping']['address'], #порядок как в models
city=data['shipping']['city'],
state=data['shipping']['state'],
zipcode=data['shipping']['zipcode'],
)
else:
print('User is not logged in...')
return JsonResponse('Payment complete!', safe=False)
models.py
from django.db import models
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_addet = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
total = self.product.price * self.quantity
return total
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
address = models.CharField(max_length=200, null=False)
city = models.CharField(max_length=200, null=False)
state = models.CharField(max_length=200, null=False)
zipcode = models.CharField(max_length=200, null=False)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.store, name="store"),
path('cart/', views.cart, name="cart"),
path('checkout/', views.checkout, name="checkout"),
path('update_item/', views.updateItem, name="update_item"),
path('process_order/', views.processOrder, name="process_order"),
]
I reviewed the lesson several times, code seems to be without mistakes.
Server side error
The error is because you didn't declared shipping variable in your Orders model.
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
shipping = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
Go to models file and update the Order class with above code.
client side
While making API request set the header Content-Type to text/html.
Because the API is responding HTML file not json.
That's why you have an error in browser.
in Order model there should be a field named shipping which is require in the processorder view.
just add below field in Order model
shipping = models.BooleanField(default=False)
since you want ot hide it , then a property need to be added not the db field
so your model should look like this
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
#property
def shipping(self):
shipping = False
# add shipping logic here
return shipping
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
follow the tutorial a little more, you will be able to grasp the solution.

Error 'Product' object has no attribute '_combinator_query'

I am creating an e-commerce website in django where the homepage can be changed dynamically by changing the instances of FeaturedProduct objects. These objects have two ForeignKeys. First is to the Product class and the other is to FeaturedCategory class(this is for the type of deal, eg: daily deals, new arrivals, etc). So, I'm trying to get the Product instances in a queryset instead of the FeaturedProduct queryset. When I union two querysets, I get an error that 'Product' object has no attribute '_combinator_query'. The codes have been shown below.
My models.py
class Product(models.Model):
product_id = models.AutoField
product_name = models.CharField(max_length=50, unique=True)
category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT, default='1')
sub_category = models.ForeignKey(SubCategory, on_delete=models.SET_DEFAULT, default='2')
price = models.IntegerField(default=0)
stock = models.IntegerField(default=0)
desc = models.TextField()
pub_date = models.DateField()
avg_rating = models.IntegerField(default=0)
avg_rating_float = models.FloatField(default=0.0)
number_of_ratings = models.IntegerField(default=0)
image1 = models.ImageField(upload_to="images", default="")
image2 = models.ImageField(upload_to="images", default="")
image3 = models.ImageField(upload_to="images", default="")
slug = models.SlugField(blank=True, help_text=('Leave this parameter empty, it will get generated automatically.'))
def save(self, *args, **kwargs):
self.slug = slugify(self.product_name)
super(Product, self).save(*args, **kwargs)
def __str__(self):
return self.product_name
class FeaturedCategory(models.Model):
category = models.CharField(max_length=100)
def __str__(self):
return self.category
class Meta:
verbose_name_plural = "Featured Categories"
class FeaturedProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
featured_category = models.ForeignKey(FeaturedCategory, on_delete=models.CASCADE)
def __str__(self):
return self.product.product_name
My views.py
def index(request):
prod = Product.objects.none()
feat = FeaturedProduct.objects.all()
for pro in feat:
ob = Product.objects.get(product_name=pro.product)
print(ob.product_name)
print(ob.category)
print(ob.sub_category)
print(ob.price)
prod.union(ob) # Error found here
# Working part
products = Product.objects.all()
context = {'products': products}
return render(request, 'index.html', context)
The last three lines are working fine, but not the other part of the index function.
Please help. Thank You.

I am getting ERROR: AttributeError at /customer/5/ type object 'Customer' has no attribute 'orderitem_set'

Please help me I stuck at this problem. When Click on the view button I want to show all the orders from that user as shown in the image below, but when i click on it I am getting this error instead of order details for that customer.
The models file contains
models.py
class Customer(models.Model):
user = models.OneToOneField(
User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=50, null=True)
phone = models.CharField(max_length= 200, null = True)
email = models.CharField(max_length=100)
def __str__(self):
return self.name
class Order(models.Model):
customer = models.ForeignKey(
Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=True)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.customer)
#property
def shipping(self):
shipping = False
orderitems = self.orderitem_set.all()
for i in orderitems:
if i.product.digital == False:
shipping = True
return shipping
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
customer = models.ForeignKey(
Customer, on_delete=models.SET_NULL, null=True, blank=True)
product = models.ForeignKey(
Product, on_delete=models.SET_NULL, null=True, blank=True)
order = models.ForeignKey(
Order, on_delete=models.SET_NULL, null=True, blank=True)
quantity = models.IntegerField(default=0, null=True, blank=False)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.product.name
#property
def get_total(self):
total = self.product.price * self.quantity
return total
The views.py file contains
Views.py
#login_required(login_url='login')
#admin_only
def customer(request, pk):
customer = Customer.objects.get(id=pk)
orders = Customer.orderitem_set.all()
shippinginfo = customer.shippingaddress_set.all()
total_order = orders.count()
context = {'customer': customer, 'orders': orders, 'total_order':total_order, 'shippinginfo': shippinginfo}
return render(request, 'store/customer.html', context)
Do it like :-
def customer(request, pk):
customer = Customer.objects.get(id=pk)
orders = customer.orderitem_set.all()
shippinginfo = customer.shippingaddress_set.all()
total_order = orders.count()
What i have changed ?
I have related (connected) orderitem_set with the existing id with existing query.
EDIT :-
I have found the problem in your GitHub Repo.
The Problem is in the updateItem view.
You're saving the order but you're not relating the request.user as a customer with the order.
So do it like :-
def updateItem(request):
data = json.loads(request.body)
productID = data['productID']
action = data['action']
print('Action:', action)
print('productID:', productID)
customer = request.user.customer
product = Product.objects.get(id=productID)
order, created = Order.objects.get_or_create(customer=customer, complete=False)
orderItem, created = OrderItem.objects.get_or_create(order=order, product=product)
if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)
# Add this line
orderItem.customer = request.user.customer
orderItem.save()
if orderItem.quantity <= 0:
orderItem.delete()
return JsonResponse('Item was added', safe=False)
Add a related_name field in your models.py on Order model like
class Order(models.Model):
customer = models.ForeignKey(
Customer, on_delete=models.SET_NULL, null=True, blank=True, related_name="orders")
And then in views.py
def customer(request, pk):
customer = Customer.objects.get(id=pk)
orders = customer.orders.all()

how to fetch table field in other field

I have a cart and subcategory model. I want to fetch the price of the service. How I fetch the price of service in the price field.
I want to fetch price of service in the price field.
Here is my models.py
class SubCategory(models.Model):
name = models.CharField(max_length=254, unique=True)
id_parent = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
price = models.IntegerField()
status = models.BooleanField(default=True)
def __str__(self):
return self.name
class Cart(models.Model):
user = models.ForeignKey('accounts.User', related_name="carts", null=True, on_delete=models.SET_NULL)
quantity = models.IntegerField(default=1)
service = models.ForeignKey('accounts.SubCategory',null=True, on_delete=models.SET_NULL)
price = models.ForeignKey('accounts.SubCategory', on_delete=models.CASCADE, default=None, blank=True, related_name='subprice')
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.price.price)
You would not need to select a value for price since it's derived from the service you selected.
class SubCategory(models.Model):
name = models.CharField(max_length=254, unique=True)
id_parent = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
price = models.IntegerField()
status = models.BooleanField(default=True)
def __str__(self):
return self.name
class Cart(models.Model):
user = models.ForeignKey('accounts.User', related_name="carts", null=True, on_delete=models.SET_NULL)
quantity = models.IntegerField(default=1)
service = models.ForeignKey('accounts.SubCategory',null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.service.price) # if you want just the price of the single service
#property
def total_price(self):
if self.service is not None:
return self.service.price * self.quantity
return 0
service = SubCategory(name="Help with Django", price=5)
aCart = Cart(user=1, quantity=2, service=service)
print(aCart.total_price) # 10
If I understand you clear, you just want to get price of SubCategory attached to Cart. If so, you don't need to add price field to Cart model to get SubCategory price.
You can just define price property on Cart model like this and use it in admin like a regular field:
class Cart(models.Model):
user = models.ForeignKey('accounts.User', related_name="carts", null=True, on_delete=models.SET_NULL)
quantity = models.IntegerField(default=1)
service = models.ForeignKey('accounts.SubCategory',null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True)
#property
def price(self):
if self.service:
return self.service.price
return None
#property
def total(self):
if self.service:
return self.service.price * self.quantity
return None
def __str__(self):
if self.price:
return str(self.price)
return "Can't show price with no service selected"

Django int() argument must be a string, a bytes-like object or a number, not 'OrderItem'

I am coding for a online store, and the views cannot get the parameter. Where did I go wrong?
Models.py has 3 models, the product model, order model and order_item model for creating order and save to cart:
class Product(models.Model):
product_name = models.CharField(max_length=200)
price = models.DecimalField(decimal_places=2, max_digits=10, blank=True)
created = models.DateTimeField(auto_now=True)
img = models.ImageField(upload_to='product', height_field=None, width_field=None, max_length=100, default='https://res.cloudinary.com/hsvaxmvxo/image/upload/v1594136644/product/coming_soon_uqxysa.jpg')
description = models.TextField(blank=True, null=True)
Hot = models.BooleanField(default=False)
type = models.CharField(
max_length=2,
choices=PRODUCT_CHOICES,
default=DECORATION,
)
status = models.IntegerField(choices=STATUS, default=0)
slug = models.SlugField(max_length=200, unique=True)
def __str__(self):
return self.product_name
def get_absolute_url(self):
return f"{self.slug}"
def get_add_to_cart_url(self):
return reverse("add_to_cart", kwargs={'slug':self.slug})
def remove_from_cart_url(self):
return reverse("remove_from_cart", kwargs={'slug':self.slug})
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
item = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
ordered = models.BooleanField(default=False)
def __str__(self):
return f"{self.quantity} of {self.item.product_name}"
def get_total_price(self):
return self.quantity * self.item.price
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
def __str__(self):
return self.user.username
The add to cart function in views.py:
def add_to_cart(request, slug):
item = get_object_or_404(Product, slug=slug)
order_items = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
if order.items.filter(item__slug=item.slug).exists():
order_items.quantity += 1
order_items.save()
else:
order.items.add(order_items)
return redirect('product_detail', slug=item.slug)
else:
ordered_date = timezone.now()
order = Order.objects.create(user=request.user, ordered_date=ordered_date)
order.items.add(order_items)
return redirect('product_detail', slug=item.slug)
But when I use the add_to_cart function will show the error as below:
int() argument must be a string, a bytes-like object or a number, not 'OrderItem'
The .get_or_create(…) method [Django-doc] returns a 2-tuple with as second element a boolean that specifies if it create a new object. You thus can unpack the 2-tuple to obtain the first item:
order_items, __ = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
Since this is however a singular item, you might want to rename the order_items to order_item to make it clear that this is an OrderItem object, not a collection of OrderItems.

Categories