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?
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')
]