I am working on a project where everything works out aside some litle part of code which has to return the total price of items in the cart, but it only returns the price of the first item in the cart.
Here is the code, it doesn't add all the price in the loop.
models.py
class Item (models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
d_price = models.FloatField(blank=True, null=True)
tax = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
crated = models.DateTimeField(auto_now_add=True)
photo = models.ImageField(upload_to='photos', null=False, blank=False)
image1 = models.ImageField(upload_to='photos', null=False, blank=False)
image2 = models.ImageField(upload_to='photos', null=False, blank=False)
image3 = models.ImageField(upload_to='photos', null=False, blank=False)
image4 = models.ImageField(upload_to='photos', null=False, blank=False)
def __str__(self):
return self.title
class OrderItem (models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
def __str__(self):
return f"{self.quantity} of {self.item.title}"
def total_price(self):
return self.quantity * self.item.price
def total_d_price(self):
return self.quantity * self.item.d_price
def saving(self):
return self.total_price() - self.total_d_price()
def get_total_price(self):
if self.item.d_price:
return self.total_d_price()
else:
return self.total_price()
class Order (models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
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
#property
def final_price(self):
total = 0
for order_item in self.items.all():
total += order_item.get_total_price()
return total
Related
I'm a beginner in Django.
I was trying to add a method inside the OrderItem class. But the visual studio code is showing an indentation error.
I'm not sure what is wrong here.
Anyone can help me, please?
Here is the code:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
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=True)
#image needs to be added
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, null=True, blank=True)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
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=1, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
return self.product.price * self.quantity
The indentation error is showing on the #property and get_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
Pelase see the attached screenshot.
The #property decorator should be indented at the same level of the method and fields, so:
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=1, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
return self.product.price * self.quantity
Likely you want the quantity to be by default 1. It is also not clear to me why that is a nullable field.
As a general rule-of-thumb please do not mix spaces and tabs. It might be better to always use spaces.
I need to get the user who placed the highest bid for the listing on an auction site.
models.py:
class Listing(models.Model):
class Category(models.TextChoices):
BOOKS = 'Books'
SPORTS = 'Sports'
DEATHLY_HALLOWS = 'Deathly Hallows'
CLOTHING = 'Clothing'
WANDS = 'Wands'
JEWELRY = 'Jewelry'
title = models.CharField(max_length=64)
description = models.TextField(max_length=320)
starting_bid = models.DecimalField(max_digits=10, decimal_places=2, default=0)
current_price = models.DecimalField(max_digits=10, decimal_places=2, default=0 )
img_url = models.URLField(blank=True)
category = models.CharField(choices=Category.choices, max_length=64, blank=True)
is_closed = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
winner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="Winner")
def __str__(self):
return f"{self.title}"
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, default=1)
bid = models.DecimalField(max_digits=10, decimal_places=2)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name="Bidder")
views.py:
def listing(request, listing_id):
highest_bid = Bid.objects.aggregate(Max('bid'))
winner = highest_bid.user
print(winner)
Returns the error: 'dict' object has no attribute 'user'.
How can I get the user from the maximum bid placed on the listing?
Order the Bids by the bid:
def listing(request, listing_id):
highest_bid = Bid.objects.latest('bid')
winner = highest_bid.user
print(winner)
# …
I am trying to filter my many to many variation fields with respect to the product. means, I only want the variations related to the current product to show in the admin page. now its showing all the variations available for every product.
I added formfield_for_manytomany() function to my admin.py but how can I get the current product(id) in the cart or order to filter the variations?
most of the questions in stack overflow Is based on the current user, which is easy to get? but how should I get the specific product(id) that is opened in the admin panel.
admin.py
from django.contrib import admin
from .models import *
from products.models import Variation
class CartAdmin(admin.ModelAdmin):
list_display = ('cart_id', 'date_created')
class CartItemAdmin(admin.ModelAdmin):
list_display = ('user','cart', 'product', 'quantity','is_active')
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "variation":
product = Products.objects.get(id='??') # how I get the current product in the cart or order
kwargs["queryset"] = Variation.objects.filter(product=product.id)
return super().formfield_for_manytomany(db_field, request, **kwargs)
admin.site.register(Cart, CartAdmin)
admin.site.register(CartItem, CartItemAdmin)
CartItem Model
class CartItem(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField()
is_active = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
def item_total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product.name
Product and Variation Model
class Products(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = AutoSlugField(populate_from='name', max_length=100, unique=True)
isbn = models.CharField(max_length=20, unique=True, blank=True, null=True)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
language = models.ForeignKey(Language, on_delete=models.SET_NULL, null=True)
author = models.CharField(max_length=100)
Publisher = models.CharField(max_length=100, blank=True, default=None)
release_date = models.DateField(blank=True, null=True, default=None)
price = models.IntegerField(default=None)
stock = models.IntegerField(default=None)
is_available = models.BooleanField(default=True)
cover_image = models.ImageField(upload_to='images/products')
image1 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image2 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image3 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
description = models.TextField(max_length=2000, blank=True, default=None)
create_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
number_of_pages = models.IntegerField(blank=True, null=True)
weight = models.IntegerField(blank=True, null=True)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
spine_width = models.IntegerField(blank=True, null=True)
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def get_url(self):
return reverse('product-view', args=[self.slug])
def __str__(self):
return self.name
class Variation(models.Model):
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation_category = models.CharField(max_length=100, choices=variation_category_choice)
variation_value = models.CharField(max_length=100, choices=variation_value_choice)
is_available = models.BooleanField(default=True)
date_added = models.DateTimeField(auto_now_add=True)
objects = VariationManager()
def __str__(self):
return self.variation_value
Hello in my order model i have these fields :
class Order(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name="product")
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
fname = models.CharField(max_length=100, null=True)
address = models.CharField(max_length=1000, null=True)
phone = models.CharField(max_length=12, null=True)
price = models.IntegerField()
date = models.DateField(datetime.datetime.today, null=True)
status = models.ForeignKey(
Status, on_delete=models.CASCADE, blank=True, null=True)
payment_method = models.ForeignKey(
PaymentMethod, on_delete=models.CASCADE, blank=True, null=True)
total = models.IntegerField(null=True, blank=True)
From here i have total field where i want to create a result depend on quantity and price.For an example price * quantity = total
After that i want to fetch only the total
I am new in django really confused about this Please help
You suppose to correct your total field indentation. I do not know whether it is mistake or you are trying to do that way.
what you suppose to do is.
class Order:
total = models.IntegerField(blank=True, null=True)
For that you can overload Save method of the model. This is the way you can do is:
def save(self, *args, **kwargs):
self.total = self.quantity * self.price
return super().save(self,*args, **kwargs)
class Order(models.Model):
quantity = models.IntegerField(default=1)
price = models.IntegerField()
#property
def get_total(self):
total = self.price * self.quantity
return total
I have created a e-commerce project. I have 3 models. Item, CartItem, Placeorder(checkout). I am looping through user's cart which has multiple items so that I can get each item and make a placeorder instance. But the for loop works only for the first time and when I try to placeorder(checkout) again with multiple items, the old data(records) are deleted and replaced by new data in the for loop. I do not understand this behavior. I cannot get past this. Maybe I am making some silly mistake.
models.py
SUB_CATEGORY_CHOICES = (
('Veg','Veg'),
('Non-Veg','Non-Veg'),
)
QUANTITY_CHOICES = (
('Half','Half'),
('Full','Full')
)
class Item(models.Model):
name =models.CharField(max_length=1000)
description =models.CharField(max_length=2000)
# snacks, maincourse, soups, rice, ice-cream
category =models.CharField(max_length=1000)
# veg, non-veg
# sub_category =models.CharField(max_length=1000,blank=True,null=True)
sub_category =models.CharField(choices=SUB_CATEGORY_CHOICES, max_length=1000)
images1 =models.FileField(upload_to='food_image',blank=True,null=True)
images2 =models.FileField(upload_to='food_image',blank=True,null=True)
price =models.CharField(max_length=500)
add_date =models.DateTimeField(default=timezone.now)
# half, full
quantity_size =models.CharField(choices=QUANTITY_CHOICES,max_length=1000, blank=True,null=True)
avg_rating =models.FloatField(default='0',blank=True,null=True)
def __str__(self):
return '%s - %s - %s' % (self.id,self.name,self.price)
class Meta:
ordering = ['-add_date']
class CartItem(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
the_item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
price = models.IntegerField()
def __str__(self):
return '%s - %s' % (self.the_item.name, self.the_item.sub_category)
class Placeorder(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
order_items = models.ForeignKey(CartItem, on_delete=models.CASCADE)
item_quantity = models.IntegerField(default=1)
first_name = models.CharField(max_length=200, null=True)
last_name = models.CharField(max_length=200, null=True)
shipping_phone_number = models.IntegerField(null=True)
shipping_address_1 = models.CharField(max_length=500, null=True)
shipping_address_2 = models.CharField(max_length=500, null=True)
shipping_city = models.CharField(max_length=200, null=True)
shipping_district = models.CharField(max_length=200, null=True)
shipping_state = models.CharField(max_length=200, null=True)
shipping_zipcode = models.IntegerField(null=True)
billing_phone_number = models.IntegerField(null=True)
billing_address_1 = models.CharField(max_length=500, null=True)
billing_address_2 = models.CharField(max_length=500, null=True)
billing_city = models.CharField(max_length=200, null=True)
billing_district = models.CharField(max_length=200, null=True)
billing_state = models.CharField(max_length=200, null=True)
billing_zipcode = models.IntegerField(null=True)
payment_mode = models.CharField(default='', max_length=100,null=False,blank=False)
date_added = models.DateTimeField(default=timezone.now)
delivered = models.BooleanField(default=False)
customer_delivered = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.username} -- {self.order_items.the_item}'
views.py
def checkout_page(request):
items = CartItem.objects.filter(user=request.user)
cart_total = CartItem.objects.filter(user=request.user).aggregate(Sum('price'))
context = {
'cart_total': cart_total['price__sum'],
'items':items,
'total_items':len(items),
}
return render(request, 'resto/newcheckout.html', context)
def checkout_action(request):
items = CartItem.objects.filter(user=request.user)
if request.method == 'POST':
shipping_phone_number = request.POST.get('shipping_phone_number')
shipping_address_1 = request.POST.get('shipping_address_1')
shipping_address_2 = request.POST.get('shipping_address_2')
shipping_city = request.POST.get('shipping_city')
shipping_district = request.POST.get('shipping_district')
shipping_state = request.POST.get('shipping_state')
shipping_zipcode = request.POST.get('shipping_zipcode')
billing_phone_number = request.POST.get('billing_phone_number')
billing_address_1 = request.POST.get('billing_address_1')
billing_address_2 = request.POST.get('billing_address_2')
billing_city = request.POST.get('billing_city')
billing_district = request.POST.get('billing_district')
billing_state = request.POST.get('billing_state')
billing_zipcode = request.POST.get('billing_zipcode')
payment_mode = request.POST.get('COD')
same_billing_address = request.POST.get('same_billing_address')
for item in items:
checkout_item = CartItem.objects.get(id=item.id)
print('item.pk: ', item.pk)
checkout_instance = Placeorder(
user=request.user,
order_items=item,
item_quantity=item.quantity,
first_name=request.user.first_name,
last_name=request.user.last_name,
shipping_phone_number=shipping_phone_number,
shipping_address_1=shipping_address_1,
shipping_address_2=shipping_address_2,
shipping_city=shipping_city,
shipping_district=shipping_district,
shipping_state=shipping_state,
shipping_zipcode=shipping_zipcode,
)
checkout_instance.save()
return HttpResponseRedirect(reverse('myorders'))
I gues your return HttpResponseRedirect(reverse('myorders')) should has less indent, otherwise you get return after first iteration of loop
def checkout_action(request):
items = CartItem.objects.filter(user=request.user)
if request.method == 'POST':
...
for item in items:
...
return HttpResponseRedirect(reverse('myorders'))