UniqueConstraint not working!

class RestockNotification(models.Model): 
    email = models.EmailField(max_length=255, null=True, blank=True)
    whatsapp_number = models.CharField(
        max_length=255, null=True, blank=True, validators=[validate_phone_number]
    )
    product_entry = models.ForeignKey(
        "ProductEntry", on_delete=models.CASCADE, related_name="product_notifications"
    )

    class Meta:
        constraints = [
            UniqueConstraint(
                fields=['email', 'product_entry'],
                condition=models.Q(email__isnull=False),
                name='unique_email_with_product'
            ),
            UniqueConstraint(
                fields=['whatsapp_number', 'product_entry'],
                condition=models.Q(whatsapp_number__isnull=False),
                name='unique_whatsapp_number_with_product'
            ),
        ]

the UniqueConstraint not apply uniqueness over (email,ProductEntry) and (whatsapp_number,ProductEntry) as expected, and i can create duplicated instances!!
here is an example of my data:

product_entry = ProductEntry.objects.get(id=1)
obj = RestockNotification.objects.create(
    email="omar.raafat@bit68.com",
    product_entry=product_entry,
)

I have executed the create operation multiple times in my shell and it works each time and create new instance!! what i am doing wrong??

I am using Django 2.2.16 and python 3.12 and my database is MySQL 5.7

I have tried this in my test lab and I am unable to recreate the symptoms you describe here. Any attempt to repeat the create, fails.

Please verify this as being accurate. Django 2.2 is beyond its End-Of-Life date, and is not compatible with Django 3.12.

If you’re actually using Django 4.2 and this is just a typo, please identify which subversion of 4.2 you are using, because 4.2 does not support Python 3.12 until 4.2.8. (See FAQ: Installation | Django documentation | Django)

Also please verify that you have done a makemigrations and migrate after adding these constraints.

hello,
I am already using Django 2.2.16 and latest version of python 3.12.2 on docker and MySQL 5.7 as my database and i guess the issue came from MySQL support for conditional unique constraint.

And yes i have done the makemigrations and migrate commands.

That is correct. (Documented at Model index reference | Django documentation | Django)

1 Like

Thanks a lot,
if can i ask another question, may I ask about how to handle the error returns from the UinqueContraint as it returns 500, where can i override it and handle it correctly with Django 2.2.16 as u can’t upgrade my project now?

I’d remove the constraint. I can’t see any reason to have it present if it’s not going to work in your environment.

1 Like

what do you suggest to me to use instead of the constraint ?

That depends upon how you are adding data and the number of different places in your code that data gets added to that model.

If all additions are being made in one location in your code (one view or one function being called by views), you could add the test for a duplicate entry in that location using get_or_create, along with whatever other conditions you wish to enforce.

If you’re adding data to this model in multiple locations through your system, but still relying on create, then you could override the model’s save method and handle this there.

Unfortunately, neither of the two methods above will work with a bulk_create or bulk_update - both of which bypass the individual model methods. In this situation, you’re out of luck. You’ll either need to convert your process using those methods to other methods, or change how you’re creating the instances to be added (or updated) to test for validity of those entries.

1 Like

i have only one view that creates an instance only, so i see there are three options:
1- overriding clean method of the model.
2- move this logic in serialzier's validate method
3- using before_create hook