-1

Just starting out with Django. I am trying to create a custom manage.py called "average" whose function is to compute the average of each field from Review model and update it in the "AvgMarks" model.

The models are :

class AvgMarks(models.Model):
collegeId = models.ForeignKey(College)
overall = models.FloatField()
academics = models.FloatField()
sports = models.FloatField()

class Reviews(models.Model):
collegeId = models.ForeignKey(College)
dateAdded = models.DateField(default=timezone.now())
authorName = models.CharField(max_length=25)
authorEmail = models.EmailField(max_length=100)
authorYear = models.IntegerField()
authorCourse = models.CharField(max_length=50)
category = models.CharField(max_length=20, choices=CATEGORIES)
marks = models.FloatField(default="1.00")
review = models.TextField()

def __str__(self):
    return self.authorName

The content of "average.py" for manage.py is:

from django.core.management.base import BaseCommand, CommandError
from django.db.models import Avg
from college.models import AvgMarks, College
from reviews.models import Reviews

class Command(BaseCommand):
help = "Calculates and save the average for a particular field"

def handle(self, *args, **options):
    colleges = College.objects.all()
    for i in colleges:
        AvgMarks.objects.filter(collegeId=i).update(
            overall = Reviews.objects.filter(collegeId=i).aggregate(Avg('marks'))['marks__avg'],
            academics = Reviews.objects.filter(collegeId=i, category="Academics").aggregate(Avg('marks'))['marks__avg'],
            sports = Reviews.objects.filter(collegeId=i, category="Sports").aggregate(Avg('marks'))['marks__avg'],
        )

    self.stdout.write("Averages done!")

On running "python manage.py average" command in Windows Powershell, I am getting the following error: django.db.utils.IntegrityError: college_avgmarks.overall may not be NULL

How do I fix it? TIA

1 Answers1

0

Before doing the AvgMarks.objects.filter().update() do poor-mans debugging

print(Reviews.objects.filter(collegeId=i).aggregate(Avg('marks'))['marks__avg'])

you'll see that it can become None from time to time (Avg returns None if there's no data to process) and overall isn't allowed to be None/NULL in your model definition.

Have a condition around it:

overall = Reviews.objects.filter(collegeId=i).aggregate(Avg('marks'))['marks__avg']
if overall is None:
    overall = 0

...update(overall=overall, ...)

You might also want to do this for the other Avgs

Chris Schäpers
  • 1,238
  • 10
  • 17
  • Thanks! Instead of trying to averaging the overall, because sometimes it become None, I calculated the individual category averages and then took out their arithmetic mean to compute overall average. – user3589022 Aug 16 '15 at 18:00