how to calculate sum of #property function in django model? - python

I want to calculate the sum of total_amount property. Here is my models.py
class Orders(models.Model):
order_id = models.AutoField(primary_key=True)
order_item = models.ForeignKey('Product', models.DO_NOTHING, db_column='order_item', blank=True, null=True,
related_name='ordered_item')
order_status = models.CharField(max_length=100, blank=True, null=True)
delivery_address = models.TextField(blank=True, null=True)
customer = models.ForeignKey('User', models.DO_NOTHING, db_column='customer', blank=True, null=True)
quantity = models.IntegerField()
date_time = models.DateTimeField()
#property
def total_amount(self):
rate = Product.objects.get(pk=self.order_item.product_id)
total_amount = rate.price * self.quantity
return total_amount
#property
def unit_rate(self):
rate = Product.objects.get(pk=self.order_item.product_id)
return rate.price

You do not need a property method for that. Instead use annotate like this:
from django.db.models import Sum, F, ExpressionWrapper, DecimalField
Orders.objects.filter(date_time__month=6).annotate(
total_amount = ExpressionWrapper(
F('order_item__price')*F('quantity'),
output_field=DecimalField()
)
).aggregate(monthly_total=Sum('total_amount'))['monthly_total']

Related

How to filter Many to Many field in django admin page using a foreign key value?

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

How to count items when their quantity is below reorder level in django

Im confused in counting the items that are quantities are below reorder level. The reorder level is a column in the model of an item too, i think i need to compare their values in __lte in filters but it's not working.
Models.py
class Item(models.Model):
ItemName = models.CharField(max_length=255, blank=True, null=True)
Quantity = models.IntegerField(null=True, default=1,
validators=[
MaxValueValidator(100),
MinValueValidator(0)
])
ModelNum = models.CharField(max_length=255, blank=True, null=True)
Category = models.ForeignKey(Category,on_delete=models.CASCADE, null=True)
date_created = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
is_draft = models.BooleanField(default=True)
reorder_level = models.IntegerField(blank=True, default=10,
validators=[
MaxValueValidator(100),
MinValueValidator(1)
])
class Meta:
verbose_name_plural = 'Item'
def __str__(self):
return f'{self.ItemName}'
Views.py
def dashboard_inventory(request):
items_count = Item.objects.all().count()
reorder_count = Item.objects.filter(Quantity_lte=reorder_level).count()
context={
'items_count' : items_count,
}
template_name ='inventory-admin/inventory-dashboard.html'
return render(request, template_name, context)
You can use F expressions to compare those two columns like this:
from django.db.models import F
Item.objects.filter(Quantity__lte=F('reorder_level')).count()
This will get all Items with Quantity less than or equal to its own reorder_level

How to assign the same value to multiple variables in a class in django models

In the below class orders, I want to assign the same value of weight to the amount
class Orders(models.Model):
consignment_id = models.IntegerField(primary_key='consignment_id', auto_created=True)
order_date = models.DateTimeField(default=timezone.now)
weight = models.FloatField()
from_place = models.CharField(max_length=20, null=True)
destination = models.CharField(max_length=20)
amount = models.FloatField(weight)
name = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=20, default='Pending')
You should use the save function in the model
class Orders(models.Model):
consignment_id = models.IntegerField(primary_key='consignment_id', auto_created=True)
order_date = models.DateTimeField(default=timezone.now)
weight = models.FloatField()
from_place = models.CharField(max_length=20, null=True)
destination = models.CharField(max_length=20)
amount = models.FloatField()
name = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=20, default='Pending')
def save(self):
self.amount = self.weight
super().save(self)

I want to only fetch a specific field data

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

Getting the total of unit price * quantity

Here's an excerpt from my models:
class Order(models.Model):
...
content_type = models.ForeignKey(ContentType)
user = models.ForeignKey('auth.User')
class OrderItem(models.Model):
...
unit_price = models.DecimalField(max_digits=7, decimal_places=2, blank=True)
quantity = models.SmallIntegerField()
order = models.ForeignKey(Order)
I have a dashboard where I want to display the total of sold items. I am struggling with how I can multiply the unit_price by the quantity.
You could do this with an extra() query:
OrderItem.objects.extra(select={'total': 'unit_price * quantity'})
You could add a property total to OrderItem:
class OrderItem(models.Model):
...
unit_price = models.DecimalField(max_digits=7, decimal_places=2, blank=True)
quantity = models.SmallIntegerField()
#property
def total(self):
return unit_price * quantity
# you can then access it like any other field (but you cannot filter on it)
print OrderItem.objects.get(pk=1).total

Categories

Resources