I have model class Bid in my auction app that stores bids placed on items:
class Bid(models.Model):
title = models.CharField(max_length=64, blank=True)
date_time = models.DateTimeField(default=timezone.now, blank=True)
price = models.DecimalField(max_digits=4, decimal_places=2)
user = models.CharField(max_length=64)
I want to query all bid prices placed on a particular item:
bids = Bid.objects.all().filter(title=title)
Returns all items with that title, but I just want the price column. I tried :
bids = bids.price
But it didn't work.
If you need only the prices based on the title of bid :
bids = Bid.objects.all().filter(title=title).values_list("price", flat = True)
You need to use a loop to get all prices:
bids = Bid.objects.filter(title=title)
for bid in bids:
print(bid.price)
This is because the query returns a list.
Related
I have a question here, I have two tables in my django models one for listings and one for bids
class Listing(models.Model):
class Meta:
verbose_name_plural = 'Listing'
title = models.CharField(max_length=64)
description = models.TextField()
price = models.DecimalField(max_digits=5, decimal_places=2)
image = models.URLField(max_length=500, default='')
category = models.CharField(max_length=32)
created = models.CharField(max_length=32)
addedon = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.title
class Bid(models.Model):
class Meta:
verbose_name_plural = 'Bid'
user = models.ForeignKey(User, on_delete=models.CASCADE)
item = models.ForeignKey(Listing, on_delete=models.CASCADE)
bid = models.DecimalField(max_digits=5, decimal_places=2)
created = models.DateTimeField(auto_now_add=True)
what i want is to show a page with all the user won items
def won(request):
listing = Listing.objects.filter(active=False)
the question here how i can make list of all then check max bid of each listing, then check is the current user is the winner and display it in the template won.html
like :
getMaxBid = Bid.objects.filter(item_id=listing.id).aggregate(Max('bid'))
maxBid = getMaxBid['bid__max']
then if the user is the winner display it
return render(request, "auctions/won.html", {
'listing': listing, 'active': False
})
thanks in advance
You can filter the Listing by first creating a Subquery expression [Django-doc] that will obtain the winner, and then check if the logged in user (or another user) is the winner, so:
from django.db.models import OuterRef, Subquery
listing = Listing.objects.alias(
bid_winner=Subquery(
Bid.objects.filter(item=OuterRef('pk')).order_by('-bid').values('user')
)[:1]
).filter(
active=False,
bid_winner=request.user
)
or Listings where the user has an active bid:
Listing.objects.filter(
bid__user=request.user,
active=True
).distinct()
I am trying to print a particular wise total in the invoice using Django. The problem is if I use for loop, it prints the last items particular wise total in everywhere. I am confused what will be the best way to calculate individual total in their respective rows?
Here is my Views.py:
def order_complete(request):
order_number = request.GET.get('order_number')
transID = request.GET.get('payment_id')
try:
order = Order.objects.get(order_number=order_number, is_ordered=True)
ordered_products = OrderProduct.objects.filter(order_id = order.id)
total=0
subtotal = 0
for i in ordered_products:
total = i.product_price * i.quantity
subtotal += total
payment = Payment.objects.get(payment_id = transID)
context ={
'order': order,
'ordered_products': ordered_products,
'order_number': order.order_number,
'transID': payment.payment_id,
'payment': payment,
'subtotal': subtotal,
'total':total,
}
return render(request, 'orders/order_complete.html', context)
except(Payment.DoesNotExist, Order.DoesNotExist):
return redirect('home')
models.py
class OrderProduct(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
payment = models.ForeignKey(Payment, on_delete=models.SET_NULL, blank=True, null=True)
user = models.ForeignKey(Account, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
variations = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField()
product_price = models.FloatField()
ordered = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.product.product_name
template
<dd class="text-right">${{ total }}</dd>
suggestion/solutions would be highly appreciated.
Here is the result
My suggestion is to always store total_amount in the table itself along with unit_price and quantity,
Cause this way, if you ever want to get the item's unit cost you can simply access it on order table itself and total to tell that this is the total of unit price x quantity
1 more advantage you get by this i.e. when calculating the final total of all order items you can simply write the following to get it
from django.db.models import Sum
order_products = OrderProduct.objects.filter(order_id=order.id)
total_amount = order_products.aggregate(Sum('total_amount'))["total_amount__sum"]
# total_amount is the new field to add in OrderProduct table which stores
# quantity * unit_price at the time of creation
This way, you will directly get individual total & sum of those totals
I have two models with ManyToManyField relationship:
class Education(models.Model):
title = models.CharField(default=None, max_length=100)
content = models.TextField(default=None)
price = models.ManyToManyField(Price)
class Price(models.Model):
cost = models.CharField(default=None, max_length=20)
created_at = models.DateTimeField(auto_now=True, null=True, blank=True)
I can fetch all rows like this:
result = Education.objects.filter(price__in=Price.objects.all()).select_related('Price')/
.values_list('title', 'content', 'price__cost', 'price__created_at')
But now i want to group by education.id and the cost parameter should be latest parameter that inserted(based on created_at).
So i want to have list of all Education with latest cost that inserted for every education.
Will it work for you, It will return the respective id
Education.objects.filter(price__in=Price.objects.all()).select_related('Price').values('id').annotate(price_id=Max('price__id'))
I got such table structure
class Item(models.Model):
id = models.AutoField(primary_key=True)
class Car(models.Model):
vin_number = models.CharField(max_length=250, null=True, blank=True)
item = models.OneToOneField(Item, on_delete=models.CASCADE)
name = models.CharField(max_length=1000, null=True)
year = models.IntegerField(null=True)
class Yacht(models.Model):
name = models.CharField(max_length=1000, default='')
boat_type = models.CharField(max_length=1000, default='', null=True)
item = models.OneToOneField(Item, on_delete=models.CASCADE)
description = models.TextField(default='')
year = models.IntegerField(null=False, default=0)
So, both Car and Yacht has relation with Item table
If I have only item id in request, what is the right way to write such query
data = request.POST
item = Car.objects.filter(item_id=data['item_id']).first()
if not item:
item = Yacht.objects.filter(item_id=data['item_id']).first()
Is there any way not to use if/else statement?
You don't need to look into the Car and Yacht model. Directly use the Item model's OneToOne relationship
item = Item.objects.filter(id = data['id']).first
This item has a specific id that relates to one of the other model. You can access them using
if item.car:
car = item.car
else:
yacht = item.yacht
But I guess you also need to add {{ related_name='tags', related_query_name='tag' }} to your OneToOne field for both car and yacht.
I would recommend that you check this out https://kite.com/python/docs/django.db.models.ForeignKey.
For more detail go to https://docs.djangoproject.com/en/3.0/topics/db/examples/one_to_one/
You need to use exists().
Car.objects.filter(item_id=data['item_id']).exists()
Yacht.objects.filter(item_id=data['item_id']).exists()
It returns you True or False.
Links to official docs.
In the following model:
class Product(models.Model):
name = models.CharField(max_length = 255)
created_in = models.DateTimeField(auto_now=True)
class Price(models.Model):
product = models.ForeignKey(Product)
price = models.DecimalField(max_digits=6, decimal_places=2)
created_in = models.DateTimeField(auto_now=True)
I want to do things like this:
products = Product.objects.filter(price__gte=Decimal(10)) #It considered all prices I just need the last one
How do i query a product considering only the last price "created_in" related?
Thanks!!
latest() is what you need:
Returns the latest object in the table, by date, using the field_name
provided as the date field.
products = Product.objects.filter(price__gte=Decimal(10)).latest('price__created_in')