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
Related
I have an application for calculating diets based on the nutrients of each meal. In admin of this application I want to price of each meal to the Meal table, which I have managed to do by calculating the price when displaying it in admin:
# admin.py
class AdminMeal(admin.ModelAdmin):
list_display = ['name', 'meal_type_names', 'price']
#admin.display(description='Price')
def price(self, obj):
unit_prices = np.asarray(obj.mealingredient_set.order_by('id').values_list('ingredient__unit_price'))
amounts = np.asarray(obj.mealingredient_set.order_by('id').values_list('amount'))
to_return = float(np.matmul(np.transpose(unit_prices), amounts) / 1000)
return mark_safe(to_return)
Now my main question: I need to allow ordering of Meal table based on Price which I don't know how.
based on my search it seems I should use annotate instead of my current way of calculating the price to be able to sort my table, I found a solution in here
# admin.py
class AdminMeal(admin.ModelAdmin):
list_display = ['name', 'meal_type_names', 'price']
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(_price=Sum('mealingredient__amount * mealingredient__ingredient__unit_price'))
But sadly it throws this error (I think it's because i'm trying to SUM over different tables):
Unsupported lookup 'amount * mealingredient' for AutoField or join on the field not permitted. Any help is appreciated, forgive me if I have missed something obvious, I'm a beginner in django.
Some of the relevant Models for Meal table:
# models.py
class Meal(models.Model):
id = models.AutoField(primary_key=True)
meal_type = models.ForeignKey(MealType, on_delete=models.CASCADE, null=True, blank=True, related_name='meal_type')
meal_types = models.ManyToManyField(MealType, blank=True)
name = models.CharField(max_length=255, null=True, blank=True)
class MealIngredient(models.Model):
id = models.AutoField(primary_key=True)
meal = models.ForeignKey(Meal, on_delete=models.CASCADE, null=True, blank=True)
user_meal = models.ForeignKey(UserMeal, on_delete=models.CASCADE, null=True, blank=True)
ingredient = models.ForeignKey(Ingredient, on_delete=models.SET_NULL, null=True, blank=True)
amount = models.DecimalField(max_digits=14, decimal_places=4, default=0)
class Ingredient(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, null=True, blank=True)
state = models.CharField(max_length=255, null=True, blank=True)
unit_price = models.IntegerField(null=True, blank=True)
You need to use ExpressionWrapper:
from django.db.models import DecimalField, ExpressionWrapper, F, Sum
queryset = queryset.annotate(
_price=Sum(
ExpressionWrapper(
F('mealingredient__amount') *
F('mealingredient__ingredient__unit_price'),
output_field=DecimalField()
)
)
)
Am writing a simple program to allow user to get in return 8 percent of any amount they invest in the period of ten days.
The user balance in ten days will equal to Eight percent of any amount he/she invest and the percentage balance will be return into the user balance after ten days.
Look at my code below and help me.
Models.py
class Profile(models.Model):
user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
balance = models.DecimalField(default=Decimal(0),max_digits=24,decimal_places=4)
class Investment(FieldValidationMixin, models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
fixed_price = models.DecimalField(max_digits=7, decimal_places=2, nulll=True, blank=True)
percentageee = models.DecimalField(max_digits=3, decimal_places=0, nulll=True, blank=True)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
def __str__(self):
return _("{0}: (#{1}
{2}%, ${3})".format(self.__class__.__name__, self.amount, self.percentage, self.fixed_price) )
I want to fetch the percentage of the user investment amount here
Views.py
def get_percentage(self):
pef_of_amount = Investment.objects.filter(amount=self.amount).annotate(percentageee=Sum('amount'))
return '{:%}'.format(amount.percentageee / 8)
def percentile(self, days=10):
percent=Investment.objects.filter(self.amount*self.percentage)/100 in days
return percentile
#get the percentage balance of the amount invested after ten days
def get_current_balance(self,percentile):
total_expenses = Profile.objects.all().aggregate(Sum('balance')).annonate(percentile)
return get_current_balance
Here is a method to get 8% of amount:
class Investment(FieldValidationMixin, models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
fixed_price = models.DecimalField(max_digits=7, decimal_places=2, nulll=True, blank=True)
percentageee = models.DecimalField(max_digits=3, decimal_places=0, nulll=True, blank=True)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
def get_percentage(self):
return self.amount * 0.08
Here is an example of how to call it:
i = Investment()
i.amount = 100
result = i.get_percentage()
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 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']
I could'nt solve my problem even if I looked other people who had this problem.
How to create an id with foreign key? And how can I use the id?
This is my code:
class Receipt(models.Model):
amount = models.DecimalField(max_digits=5, decimal_places=2, primary_key=True)
vat = models.DecimalField(max_digits=5, decimal_places=2)
total_amount = models.IntegerField(default=0)
class ReceiptItem(models.Model):
receipt_id = models.ForeignKey('Receipt', on_delete=models.CASCADE)
product_id = models.ForeignKey('Product', on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=5, decimal_places=2)
vat = models.DecimalField(max_digits=5, decimal_places=2)
vat_rate = models.DecimalField(max_digits=5, decimal_places=2)
sub_total = models.IntegerField(default=0)
name = models.CharField(max_length=200)
class Product(models.Model):
name = models.CharField(max_length=5)
vat_rate = models.DecimalField(max_digits=5, decimal_places=2)
amount = models.IntegerField(default=0, primary_key=True)
This is the error I'm getting:
django.db.utils.IntegrityError: UNIQUE constraint failed: migros_product.amount
class Product(models.Model):
name = models.CharField(max_length=5)
vat_rate = models.DecimalField(max_digits=5, decimal_places=2)
amount = models.IntegerField(default=0, primary_key=True)
Amount is set as primary key, which means that the database will only allow 1 record per value of amount.
BUT, you've also set a default value of 0, so your DB can only create 1 record with amount = 0, whenever the amount value is not provided.
You must decide what you want. If the amount uniqueness matters, then remove default=0 and put null=True, blank=True, for example.