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.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?
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')
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).
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.
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).
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') ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With