Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django UniqueConstraint

Tags:

Context

I have the models AppVersion, App & DeployApp. In the AppVersion model users can upload APK files to the filesystem. I am using a pre_save signal to prevent uploading APK files with the same version_code for a specific App like this:

@receiver(pre_save, sender=AppVersion) def prevent_duplicate_version_code(sender, instance, **kwargs):     qs = AppVersion.objects.filter(app_uuid=instance.app_uuid, version_code=instance.version_code)     if qs.exists():         raise FileExistsError("Version code has to be unique for a specific app") 

This signal does what I want, except it also raises the error when I am trying to create an object in the bridge-table DeployApp.

Models

# models.py  class App(models.Model):     app_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)     app_name = models.CharField(max_length=100)   class AppVersion(models.Model):     app_version_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)     app_uuid = models.ForeignKey(App, on_delete=models.CASCADE, related_name='app_versions')     app_version_name = models.CharField(max_length=100)     version_code = models.IntegerField(blank=True, null=True, editable=False)     source = models.FileField(upload_to=get_app_path, storage=AppVersionSystemStorage())    class DeployApp(models.Model):     deploy_app_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)     app_version = models.ForeignKey(AppVersion, on_delete=models.CASCADE)     device_group = models.ForeignKey(DeviceGroup, on_delete=models.CASCADE)     release_date = UnixDateTimeField() 

My guess is that when creating an object of DeployApp the related AppVersion is also saved and thus the pre_save signal is called and raises the Exception.

I also tried to override the save() method for the AppVersion model but the results are the same.

How do I make sure that the Exception only happens upon creating a new AppVersion instance and does not happen when adding or editing a DeployApp instance?

like image 687
Stevy Avatar asked May 07 '19 13:05

Stevy


People also ask

What is UniqueConstraint in Django?

UniqueConstraint. condition. A Q object that specifies the condition you want the constraint to enforce. For example: UniqueConstraint(fields=['user'], condition=Q(status='DRAFT'), name='unique_draft_user')

What is unique together in Django?

unique_together may be deprecated in the future. This is a list of lists that must be unique when considered together. It's used in the Django admin and is enforced at the database level (i.e., the appropriate UNIQUE statements are included in the CREATE TABLE statement).

How do I create a composite key in Django?

To add composite primary key in Python Django, we can set the unique_together field in the Meta class in the model class. to set unique_together to (('key1', 'key2'),) to make key1 and key2 part of the composite primary key.

What is primary key in Django model?

If you'd like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you've explicitly set Field.primary_key , it won't add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).


1 Answers

Solved it thanks to Bear Brown his suggestion. I removed the signal and added UniqueConstraint to the AppVersion model like this:

class Meta:     db_table = 'app_version'     constraints = [         models.UniqueConstraint(fields=['app_uuid', 'version_code'], name='unique appversion')     ] 
like image 145
Stevy Avatar answered Sep 23 '22 19:09

Stevy