Create a view/template that allows for user selected date filtering that includes Sum totals for child objects?

StackOverflow https://stackoverflow.com/questions/23418121

سؤال

I've got two models along these lines:

class User(models.Model):
    name = models.CharField(max_length=50, blank=False)

class Transaction(models.Model):
    user = models.ForeignKey(User, blank=False)
    description = models.CharField(max_length=50, blank=False)
    total = models.DecimalField(default=0, decimal_places=2)
    date = models.DateField(blank=True)
    year = models.CharField(max_length=4) 
    type = models.CharField(max_length=1, db_index=True, choices=(
        ('C', 'Cash'),
        ('V', 'Visa'),
        ('A', 'Amex'),
    )) 

I'm trying to come up with a view/template, that will allow me to display an html table/report showing each user along with the totals for each type of transaction. i.e.

User    Visa    Cash   Amex    Total
User1   $50     $75    $100    $225

This first report seems easy, a list report returning a queryset of the Users, and in the User model I created separate functions to return a total for each type of transaction (as a reverse ForeignKey), like this:

def value_visa(self):
    value = self.transaction_set.filter(user=self,type__in=('Visa')).aggregate(Sum('total'))
    return value['total__sum']

def value_all(self):
    value = self.transaction_set.filter(user=self).aggregate(Sum('total'))
    return value['total__sum']

I understand that it is likely not an ideal solution, but it's worked.

However, now I'm trying to filter the transactions included in the summary table by date (or by the string year field) and I can't quite figure out how to do it. The function method I designed would need an argument to limit the date to a specific date (which can't be provided in a template), or if I prefetch_related for the transactions (which isn't currently possible without a dev patch), I can't do the sums in the template anyway nor can I figure out how to return a queryset that includes the users and the sum totals. The date can either be provided in the URL or as a user selection on a form, doesn't matter to be very much.

Any ideas? I've been pulling my hair out with this for a while now!

Thanks in advance for any ideas!

Edit: I worked this out in a get_context_data method for the view:

users = User.objects.annotate(transactions=Count('transaction')).exclude(transactions=0).order_by('name')
for u in users:
        totals = Transaction.objects.filter(user=u,year='2012').values('type').annotate(total=Sum('total'))

With this totals becomes a dicts of the totals for each of the different values of type - so that's perfect. But, I'm not sure how to get both of those to a template - users being a QuerySet and an array of totals (since there would be one for every item in users including some that'd have no values).

هل كانت مفيدة؟

المحلول

Just to close the loop on this, I ended up doing a couple of separate queries in the view and then ran through a for loop to merge them into a single dict and passed that to the template. A bit ugly... but it worked.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top