#Custom User Model and CheckConstraint

6 messages · Page 1 of 1 (latest)

solar solar
#

Hi,

I'm trying to create a custom user model where I inherit from AbstractUser with constraints on fields which should depend on some conditions. One such field is a CharField that has a length restriction:

phonenumber = models.CharField(max_length=20)

So I added a CheckConstraint like this:

models.CheckConstraint(
    condition=models.Q(is_superuser__exact=True) | models.Q(phonenumber__length__gte=7),
    name="%(app_label)s_%(class)s_phonenumber_length",
),

The idea here is that the superuser should be exempt from this condition. But when I try to apply the migration, I get an IntegrityError because the superuser's phone number is empty. In theory, I would like to make the field more flexible by allowing some special characters and spaces between the numbers, eg. +1 (234) 456 789 or something, then normalize it before storage.

How can I solve this problem, please?

sweet kraken
#

Right so, your issue is that the phone number is empty for the records where the superuser is True.

What do you want to happen in this case? If you're looking to not apply this constraint if the phone number is empty, you should handle that in the condition.

solar solar
#

I want that the superuser does not need to put in a phone number, but that the phone number constraint should be enforced for other users. I thought I'd achieve that via "short-circuit", ie, if the first condition is true, then the second condition, which places a minimum length on the field, is not enforced. Only "normal" users should need to put in a phone number.

sweet kraken
#

And you would be right. It works fine for me:

In [7]: Foo.objects.create(name="less", flag=True)
INSERT INTO "sandbox_foo" ("name", "flag")
VALUES ('less', 1) RETURNING "sandbox_foo"."id"

Execution time: 0.000839s [Database: default]
Out[7]: <Foo: Foo object (3)>

In [8]: try:
   ...:     Foo.objects.create(name="less")
   ...: except Exception:
   ...:     print('nope!')
   ...:
INSERT INTO "sandbox_foo" ("name", "flag")
VALUES ('less', 0) RETURNING "sandbox_foo"."id"

Execution time: 0.000341s [Database: default]
nope!

Can you drop that __exact ?

solar solar
#

I have done that now, and the migration still failed. But then I deleted all the 0*.py migration files and the pycache, and then ran makemigrations and migrate again, and it worked. With the pre-existing migrations, it always failed. But changing anything with the model and then trying to add another migration, also always fails so far. Not sure what to do. At the moment, it's not too much of a problem, because I don't have any live data that I need to preserve, so I can just nuke the database and start over, but that feels wrong.

maiden ember