4
\$\begingroup\$

I want to build a simple expense tracking app in Django. Each user can create categories, and each category can have multiple expenses:

enter image description here

Additionally, I wanted to have a value field that shows the total value of the category per month. For this I am using the def save() function in the Expenses class and a def calc_category_value() function called from the signals. I was wondering if this approach is correct:

def calc_category_value(instance):
 today = date.today()
 days = calendar.monthrange(today.year,today.month)[1]
 range_start = "%s-%s-%s" % (today.year,today.month,1)
 range_end = "%s-%s-%s" % (today.year,today.month,days)
 category = Category.objects.get(id=instance.category.id)
 expenses = Expense.objects.filter(date__range=[range_start,range_end],category=category)
 total = 0
 for e in expenses:
 total += e.amount 
 category.value = total
 category.save()
class Profile(models.Model):
 id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 user = models.OneToOneField(User, on_delete=models.CASCADE)
 create_date = models.DateTimeField('date added', auto_now_add=True)
 modify_date = models.DateTimeField('date modified', default=timezone.now)
class Category(models.Model):
 id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 user = models.ForeignKey(Profile, on_delete=models.CASCADE)
 name = models.CharField(max_length=200, unique=True)
 value = models.DecimalField(max_digits=11,decimal_places=2, default=0)
 create_date = models.DateTimeField('date added', auto_now_add=True)
 modify_date = models.DateTimeField('date modified', default=timezone.now)
 class Meta:
 verbose_name_plural = "Categories"
 def __unicode__(self):
 return self.name +' (' + str(self.value) + ')'
class Expense(models.Model):
 id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
 title = models.CharField(max_length=200, blank=True)
 amount = models.DecimalField(max_digits=11, decimal_places=2,default=0)
 category = models.ForeignKey(Category, on_delete=models.CASCADE)
 date = models.DateField(default=timezone.now)
 create_date = models.DateTimeField('date added', auto_now_add=True)
 modify_date = models.DateTimeField('date modified', default=timezone.now)
 def save(self, *args, **kwargs):
 super(Expense, self).save(*args, **kwargs)
 today = date.today()
 days = calendar.monthrange(today.year,today.month)[1]
 range_start = "%s-%s-%s" % (today.year,today.month,1)
 range_end = "%s-%s-%s" % (today.year,today.month,days)
 expenses = Expense.objects.filter(date__range=[range_start,range_end],category=self.category)
 total = 0
 for e in expenses:
 total += e.amount
 self.category.value = total
 self.category.save()
 class Meta:
 verbose_name_plural = "Expenses"
 order_with_respect_to = 'category'
 def __unicode__(self):
 return self.title +', ' + str(self.amount) +' (' + self.category.name + ')'

Signals.py:

@receiver(post_delete, sender=Expense)
def post_delete(sender, instance, **kwargs):
 calc_category_value(instance)
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 26, 2017 at 20:33
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You would probably want to show total expenses in the category for each month, not just the last. So Category doesn't have a value. It has a value (which is a bad naming by the way) for each month. This can be modelled simply as a query like (pseudo sql) select sum(amount) from expenses where group = 'some group' group by date.month

And by the way you can use this declarative style here.

total = 0
for e in expenses:
 total += e.amount 
category.value = total
category.value = sum(e.amount for e in expenses)
answered May 27, 2017 at 19:59
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.