Am new to Django (and Python) and have a problem initializing my model. For every school year created in the database, I want the corresponding days (not exactly 365/366, but > 300) to be created with a default value
of 0
(a one-to-many relationship). I learned that I should not try to do this in a constructor, but after the constructor has run (and the object and its attributes have become accessible). So is this a case for using signals or should I override pre- or post-save(). And why? Or is there a third option which I have missed so far?
from django.db import models
import pandas as pd
class BaseModel(models.Model):
objects = models.Manager()
class Meta:
abstract = True
class SchoolYear(BaseModel):
start = models.DateField()
end = models.DateField()
def init_days(self):
current_date = self.start
delta = timedelta(days=1)
while current_date <= self.end:
self.days.add(schoolyear=self, date=current_date, value=0)
current_date = delta
class Day(BaseModel):
schoolyear = models.ForeignKey(SchoolYear, on_delete=models.CASCADE)
date = models.DateField()
value = models.IntegerField()
CodePudding user response:
Signals tend to be considered an anti-pattern in all but a few cases. You can accomplish the above in a readable fashion by overriding the save function for your year model, and using bulk_create to create a large number of similar objects, giving you something like:
class SchoolYear(BaseModel):
start = models.DateField()
end = models.DateField()
def save(self):
#see if this is a new year being created by checking for an ID
being_created = self.pk is None
#save it anyway (after this it does have an ID)
super().save(*args, **kwargs)
#test if this is a newly created year and create days if so
if being_created:
current_date = self.start
delta = timedelta(days=1)
days = []
#create a list of days for creation
while current_date <= self.end:
days.append(Day(schoolyear=self, date=current_date, value=0))
current_date = delta
#use bulk_create to create the list of days efficiently.
Day.objects.bulk_create(days)