[Solved]-Django models: Set default relative to another field

12👍

You cannot assign a default value on a field dependent on another before having a model instance. To achieve the same you can override the save() method of the model:

class SomeModel(models.Model):

    ...

    def save(self, *args, **kwargs):
        self.second_visit = self.first_visit + datetime.timedelta(weeks=3)
        super().save(*args, **kwargs)

2👍

You can override save or usepre_save

from django.db.models.signals import pre_save
from django.dispatch import receiver


@receiver(pre_save, sender=SomeModel)
def my_handler(sender, instance, **kwargs):
    instance.second_visit = # Set second_visit to 3 weeks after instance.first_visit

1👍

This is a late answer, but @BjornW addresses a valid concern in the comment on the accepted answer that is not addressed in the 2 provided answers (at the time of writing): Overwriting save is not the same thing as setting a default value; a default value only takes effect once, at the first instance creation, while modifying save affects every subsequent modification of an existing instance as well. The 2nd answer suffers from the same deviation of the principle of a default value.

Providing a default value relative to other attributes of self is not (yet?) possible, however you can use the pre_save signal to set a default value for a field that is relative to other fields.

Here would be an example:

# signals.py
from django.dispatch import receiver
from django.db.models.signals import pre_save
# do all necessary imports e.g.:
from .models import SomeModel

@receiver(pre_save, sender=SomeModel)
def set_default_second_visit(sender, instance, raw, **kwargs):
    """
    Set default value for `second_visit`
    """
    if instance.pk is None:
        instance.second_visit = instance.second_visit or instance.first_visit + datetime.timedelta(weeks=3)

A note might be at hand:

It is not that the pre_save signal is sent only once. Actually, it is sent whenever an instance of SomeModel is saved, i.e. also if an existing entry from the db is modified. The line if instance.pk is None: is present and necessary exactly for this reason: it makes sure that that the value is set only if the object does not yet exist in the database (i.e has no primary key yet).

👤j-i-l

Leave a comment