Skip to content
Advertisement

Django: Initialize a container model with child models when a new container is created – e.g. Todo list with default tasks

I’m trying to create a todo list as part of an application that is used to prompt a user what they must complete before the application is assessed. To achieve this I have created a TaskList model and a Task model belonging to a TaskList.

When I create a new TaskList instance (on a new application) I want to prepopulate the list with some default Tasks that will always be present on every new application. I’m relatively new to Django and Python, so I’m just looking for a push in the right direction.

Is there some kind of Django model initialize function I can override on the TaskList to create these default tasks?

Edit: Django Model Fields

class AssessmentTaskList(models.Model):
    title = models.CharField(max_length=140)
    assessment = models.ForeignKey(Assessment, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)


class Task(models.Model):
    title = models.CharField(max_length=140)
    task_list = models.ForeignKey(AssessmentTaskList, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    due_date = models.DateField(blank=True, null=True)
    completed = models.BooleanField(default=False)
    completed_date = models.DateField(blank=True, null=True)
    created_by = models.ForeignKey(User, limit_choices_to={
        'groups__name': 'Assessment Staff'}, on_delete=models.SET_NULL, null=True, related_name="applicant_task_created_by")
    system_created = models.BooleanField(default=False)
    note = models.TextField(blank=True, null=True)
    priority = models.PositiveIntegerField(blank=True, null=True)
    created_on = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)
    staff_task = models.BooleanField(default=False)

Advertisement

Answer

You can either load the initial data along with migrations or provide separate fixtures with manage.py loaddata fixturefile.json:

https://docs.djangoproject.com/en/dev/howto/initial-data/

I’d suggest using the fixtures as long as you’re just populating the initials and not changing the existing data in some way. In this case, the initial load would be an optional step and could be omitted in production/testing environments (migrations are always mandatory for execution).

EDIT: Actually what you need is to leverage the functionality of Django Signals (specifically django.db.models.signals.post_save model signal):

@receiver(post_save, sender=AssessmentTaskList)
def pre_populate_tasks(sender, instance: AssessmentTaskList, created: bool = False, **kwargs):
    if created:
        # put the pre-filled tasks here
        default_tasks = [Task(task_list=instance, ...)]
        Task.objects.bulk_create(default_tasks)
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement