Auto populate a date field when a certain choice is made in choices

I’m trying to auto populate (update) a datefield, when a certain choice is chosen by the user:
following is my code

class Tasks(models.Model):
    name = models.CharField(max_length=255)
    boat = models.ForeignKey(Boat, on_delete=models.CASCADE, null=True, blank=True)
    assigned_to = models.ForeignKey(Technician, on_delete=models.SET_NULL, null=True, blank=True)
    created_by = models.ForeignKey(Person, on_delete=models.SET_NULL, null=True, blank=True)
    created_date = models.DateTimeField(default=datetime.now, blank=True)
    completed_date = models.DateField(null=True, blank=True)

    CONDITION_STATUS = (
        ('c', 'Completed'),
        ('p', 'Pending'),
        ('i', 'Incomplete'),
    )


    status = models.CharField(
        max_length=1,
        choices=CONDITION_STATUS,
        blank=True,
        default='i',
    )

as you can see, I want, when a technicain choses completed choice, it to automatically trigger an insert on datetime to the completed_date field.

I’m trying this with a clean method in my forms.modelForm class:

class TaskForm(forms.ModelForm):

    class Meta:
        model = Task

        fields = ( 
            'created_by',
            'created_date',
            'completed_date',
	**....
            )

        def clean(self):
            cleaned_data = super().clean()
            if self.errors:
                return cleaned_data
            choice = cleaned_data.get('status')
            if choice == 'c':
                cleaned_data['completed_date'] = datetime.date.today()
            return cleaned_data
	
	**....

however it seems it is not working, and what is the best approach to it, or can point me to the right direction

thanks.

You’re not showing a status field in your form. There doesn’t appear to be anything to check.

I have managed to solve this issue by overriding the save method in my model:

  def save(self, *args, **kwargs):
        if self.status == 'c':
            self.completed_date = timezone.now()
        super().save(*args, **kwargs)

is this django’s best practiced way to accomplish my desired results, or should I introduce the status field in to my Form, and use a clean_data() method to get my desired result.

thanks

I’m not sure this is what you want either. In this case, every time this model is saved after having the status == ‘c’, the date’s going to be updated. (Whether you want this to happen is only something you can decide.)

yes, it will get updated. I think i can bypass it through the templates, for now. Thanks.

Actually, no. Your templates aren’t going to have any effect on that at all. With that setting in your model, any time a model instance is saved for any reason, when the status is ‘c’, the completed_date will be updated.

I’m suspecting that what you really want to do is only update the completed_date the first time the status becomes ‘c’.

I’ve update the logic to :

    def save(self, *args, **kwargs):
        if self.status == 'c' and self.completed_date is None:
            self.completed_date = timezone.now()
        super().save(*args, **kwargs)

so in the first time it will be saved, but if an value exists in the completed_date its value won’t be updated, can share feedback to improve

thanks

1 Like