Django 唯一约束

Ste*_*evy 17 python django unique-constraint

语境

我有模型AppVersionApp& DeployApp。在AppVersion 模型中,用户可以将 APK 文件上传到文件系统。我使用的pre_save信号,以防止同样的上传APK文件version_code的具体App是这样的:

@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")
Run Code Online (Sandbox Code Playgroud)

这个信号做我想要的,除了当我试图在 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()
Run Code Online (Sandbox Code Playgroud)

我的猜测是,在创建DeployApp相关对象时AppVersion也会保存,因此pre_save会调用信号并引发异常。

我也尝试覆盖模型的save()方法,AppVersion但结果是一样的。

如何确保异常仅在创建新AppVersion实例时发生,而在添加或编辑DeployApp实例时不会发生?

Ste*_*evy 45

感谢 Bear Brown 他的建议解决了这个问题。我删除了信号并像这样添加UniqueConstraintAppVersion模型中:

class Meta:
    db_table = 'app_version'
    constraints = [
        models.UniqueConstraint(fields=['app_uuid', 'version_code'], name='unique appversion')
    ]
Run Code Online (Sandbox Code Playgroud)