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()
Advertisement
Answer
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)