This is model:
class Purchase(models.Model):
date = models.DateField(default=datetime.date.today,blank=False, null=True)
total_purchase = models.DecimalField(max_digits=10,decimal_places=2,blank=True, null=True)
I want to perform a month wise calculation of "total_purchase" within a specific daterange in such a way that if there is no purchase in a month the total purchase should be the previous month purchase value And if there is purchase in two months then total purchase will the addition of those two...
Example:
Suppose the date range given by user is from month of April to November.
If there is a Purchase of $2800 in month of April and $5000 in month of August and $6000 in month of October.
Then the output will be like this:
April 2800
May 2800
June 2800
July 2800
August 7800 #(2800 + 5000)
September 7800
October 13800 #(7800 + 6000)
November 13800
Any idea how to perform this in django queries?
Thank you
According to the answer given by Mr.Raydel Miranda. I have done the following
import calendar
import collections
import dateutil
start_date = datetime.date(2018, 4, 1)
end_date = datetime.date(2019, 3, 31)
results = collections.OrderedDict()
result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(real_total = Case(When(Total_Purchase__isnull=True, then=0),default=F('tal_Purchase')))
date_cursor = start_date
while date_cursor < end_date:
month_partial_total = result.filter(date__month=date_cursor.month).agggate(partial_total=Sum('real_total'))['partial_total']
results[date_cursor.month] = month_partial_total
if month_partial_total == None:
month_partial_total = int(0)
else:
month_partial_total = month_partial_total
date_cursor += dateutil.relativedelta.relativedelta(months=1)
return results
But now the output is coming like this(from the example above):
April 2800
May 0
June 0
July 0
August 5000
September 0
October 6000
November 0
Do anyone have any idea how to add between the months... I want to do something like
e = month_partial_total + month_partial_total.next
I want to add the next iteration value of every month_partial_total. I think this will solve my problem..
Any idea anyone how to perform this in django?
Thank you
I've noted two things in your question:
blank
or null
.Based on those things I'll propose this approach:
You could get the total for a given month, you just need to handle the case where the total_pushase
is null (as a side note, it does not make any sense to have an instance of Purchase
where total_purchase
is null, at least it must be 0).
Read about Django Conditional expressions to learn more about When
and Case
.
# Annotate the filtered objects with the correct value (null) is equivalent
# to 0 for this requirement.
result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(
real_total = Case(
When(total_purchase__isnull=True, then=0),
default=F('total_purchase')
)
)
# Then if you want to know the total for a specific month, use Sum.
month_partial_total = result.filter(
date__month=selected_month
).aggregate(
partial_total=Sum('real_total')
)['partial_total']
You could use this in a function to achieve you wanted result:
import calendar
import collections
import dateutil
def totals(start_date, end_date):
"""
start_date and end_date are datetime.date objects.
"""
results = collections.OrderedDict() # Remember order things are added.
result = Purchase.objects.filter(date__gte=start_date, date__lt=end_date).annotate(
real_total = Case(
When(total_purchase__isnull=True, then=0),
default=F('total_purchase')
)
)
date_cursor = start_date
month_partial_total = 0
while date_cursor < end_date:
# The while statement implicitly orders results (it goes from start to end).
month_partial_total += result.filter(date__month=date_cursor.month).aggregate(
partial_total=Sum('real_total')
)['partial_total']
results[date_cursor.month] = month_partial_total
# Uncomment following line if you want result contains the month names
# instead the month's integer values.
# result[calendar.month_name[month_number]] = month_partial_total
date_cursor += dateutil.relativedelta.relativedelta(months=1)
return results
Since Django 1.11 might be able to solve this problem SubQueries, but I've never used it for subquery on the same model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With