2

I have the following model:

class User(models.Model):
    email = models.EmailField(max_length=254, null=False, unique=True)
    referral_code = models.CharField(max_length=10, null=False, unique=True)

And used the Django shell to save a user instance with referral_code undefined:

u = User(email="test@example.com")
u.save()

This did not raise an exception. My understanding was that null=False would require referral_code to be set - Is this not the case? How would I achieve that behaviour?

update

I notice that the field is set to u.referral_code='', so given the uniqueness constraint, this has raised an exception when I tried to repeat the process with a new instance. I would rather the exception was thrown because I did not set the field...

Rob
  • 617
  • 8
  • 21

1 Answers1

3

The value of your referral_code is not null, it is '' (blank string). This is the default of CharField.


Updated along with question:

You can raise an error before the data is stored in the database by overriding save on the model

class User(models.Model):
    email = models.EmailField(max_length=254, null=False, unique=True)
    referral_code = models.CharField(max_length=10, null=False, unique=True)

    def save(self, *args, **kwargs):
        assert self.email, "The 'email' field must be populated."
        super().save(*args, **kwargs)

It should be noted that this is not to be preferred over form validation where possible.


Update now that newer features of Django are available:

Django's Constraints allow you to add custom database constraints:

class User(models.Model):
    email = models.EmailField(max_length=254, null=False, unique=True)
    referral_code = models.CharField(max_length=10, null=False, unique=True)

    class Meta:
        constraints = [
            models.CheckConstraint(
                check=(~models.Q(referral_code='')),
                name='referral_code_populated',
            )
        ]
meshy
  • 8,470
  • 9
  • 51
  • 73