Possibly to nullify if not in django choices

Viewed 53

Let's say I have the following django field:

class MyModel(models.Model):

    MONTH_CHOICES = [(str(i), calendar.month_name[i]) for i in range(1,13)]
    month = models.CharField(max_length=9, choices=MONTH_CHOICES, default='1')

Let's say someone enters in 40, instead of it raising an error, I want it to just save it as None / NULL. Is there a way to do this, perhaps on the save method in a generic way?

2 Answers

Since you want to set the month field to Null, you must set null=True in the Django model and must migrate the changes

month = models.CharField(
    max_length=9,
    choices=MONTH_CHOICES,
    default='1',
    null=True
)

and then, override the save(...) method of your model as,

def save(self, **kwargs):
    if not self.pk and not 1 <= int(self.month) <= 12:
        self.month = None
    super().save(**kwargs)

Complte Example

class MyModel(models.Model):
    MONTH_CHOICES = [(str(i), calendar.month_name[i]) for i in range(1, 13)]
    month = models.CharField(
        max_length=9,
        choices=MONTH_CHOICES,
        default='1',
        null=True
    )

    def save(self, **kwargs):
        if not self.pk and not 1 <= int(self.month) <= 12:
            self.month = None
        super().save(**kwargs)

First, you need to add a null value for the model and must migrate the changes:

month = models.CharField(..., null=True)

You can use the clean method to validate your model and replace the data:

class MyModel(models.Model):

    ...

    def clean(self):
        if self.month not in self.MONTH_CHOICES:
            self.month = None
        return

Or you can use pre_save signal (more)

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

 @receiver(pre_save, sender=MyModel)
 def my_callback(sender, instance, *args, **kwargs):
     if instance.month not in instance.MONTH_CHOICES:
        instance.month = None

 
Related