0

I'm a beginner working on a school fees management software with Django. My Problem is Below:

I have two models, Student and Family:

from django.db import models

--snip--
class Family(models.Model):
    father = models.CharField(max_length=100)
    mother = models.CharField(max_length=100)
    total_fees = students.fees.aggregate(models.Sum('fees'))

    def __str__(self):
        return self.father+" " +self.mother

class Student(models.Model):
    family = models.ForeignKey(Family, on_delete=models.CASCADE, related_name='students', default='')
    name = models.CharField(max_length=100)
    date_of_birth = models.DateField('Date Of Birth')
    fees = models.IntegerField(default=0)
    email= models.CharField(max_length=200)

    def __str__(self):
        return self.name

Im trying to get all the total fees of a family by adding up the fees of all the students in the family:
total_fees = students.fees.aggregate(models.Sum('fees'))
I used the solution stated here.

but i get this error when i try to migrate:

File "/home/my_username/mysite/students_app/models.py", line 34, in Family
    total_fees = students.fees.aggregate(models.Sum('fees'))
AttributeError: 'ForeignKey' object has no attribute 'fees' 

What is the correct way to get the total fees for a family?

Thanks!

PS: This is my first question, please tell me how I can improve my questions :)

Rayyan
  • 182
  • 4
  • 16
  • 1
    What is "students" in students.fees – Ehtesham Siddiqui Jul 13 '20 at 17:49
  • I am trying to use the 'related_name' attribute.https://stackoverflow.com/questions/2642613/what-is-related-name-used-for-in-django EDIT: I did not understand related name properly. Answer below solves my problem :) – Rayyan Jul 13 '20 at 22:49

1 Answers1

1

I wouldn't consider "Total Fees" being a field of either Family or Student. I would opt for a method in the Family model that queries for the fees for all the students in that family.

First step is import the Sum aggregation function from django.db.models into your models file:

from django.db.models import Sum

Then, define the function in your Family class that does the aggregation. Note that aggregate() returns a dictionary of name-value pairs. So as you had your query previously set up, it would've returned something like: {'fees__sum': 100000}.

So you need to access the value in the dictionary by that generated key, like:

Student.objects.filter(family=self).aggregate(Sum('fees'))['fees__sum']

Putting it all together:

from django.db.models import Sum

class Family(models.Model):
    father = models.CharField(max_length=100)
    mother = models.CharField(max_length=100)

    def __str__(self):
        return self.father+" " +self.mother

    def get_students_total_fees(self):
        return Student.objects.filter(family=self).aggregate(Sum('fees'))['fees__sum']

With this, you could then have a Family object and get the fee total:

family_object = Family.objects.get(Id=1)
family_students_fees_total = family_object.get_students_total_fees()
user3750325
  • 1,502
  • 1
  • 18
  • 37
  • EDIT: This is throwing me an error!: `AttributeError: 'Manager' object has no attribute 'Filter' `Sorry for the delay – Rayyan Jul 16 '20 at 16:28
  • Hmm, I did notice I wrote "object" instead of "objects" in my query, which I have corrected in the answer. Try replacing that. – user3750325 Jul 16 '20 at 17:44
  • Yes, that was one of the errors, I corrected and it still doesn't work, however, I made some changes myself and the error may be occurring because of my changes; this solution works when I try it for another model. Thanks for your help. – Rayyan Jul 16 '20 at 23:12
  • Isn't the code wrong because the `Student` model is not defined(It is called before it is defined?) in `return Student.objects.filter(family=self).aggregate(Sum('fees'))`? Or am I incorrect? I will read Docs. – Rayyan Jul 16 '20 at 23:18
  • Tested my code and updated the answer. And no, order of definition in the model shouldn't matter. – user3750325 Jul 17 '20 at 16:35
  • Thank you. The error was because of the dictionary, it works now! – Rayyan Jul 17 '20 at 16:53
  • 1
    Also, i was typing capital 'Filter'. Correct is 'filter' – Rayyan Jul 20 '20 at 16:01