Skip to main content
 首页 » 编程设计

python之Django 。仅当为创建和更新调用提供了两个模型字段时才检查 `unique_together`

2024年08月14日28fff_TT

我需要检查 unique_together 只有在两个字段都提供给管理员创建 Form 或通过 API 请求两个 create 和 update 调用。如果发生这种情况并且字段不是 unique_together 我需要将 Exception 传播到 django-admin 创建 Form 和 RestFramework 的 Serializer/ViewSet。

这是我的模型的一个简化示例:

class MyModel(models.Model): 
    time = models.TimeField(null=True, blank=True) 
    date = models.DateField(null=True, blank=True) 
    some_other_field = models.BooleanField(default=False) 
    ... 

正如您在模型级别看到的那样,time 和 date 都不是必需的并且可以为 null。

另一方面,应用程序逻辑要求至少提供这些字段中的一个,如果同时提供这两个字段——这对对于整个表来说应该是唯一的,以避免 datetime 组合的重复。

此模型通过以下节点访问:django-admin 和 DjangoRestFramework 使用 ViewSet 的端点。

从 API 的角度来看,创建新记录似乎不是问题,我可以覆盖 Serializer 的 validate 方法:

    def validate(self, data): 
    if not data.get('time') and not data.get('date'): 
        raise serializers.ValidationError( 
            "At least one of this fields is required: time, date" 
        ) 
 
    if OpenTable.objects.filter( 
            time=data.get('time'), 
            date=data.get('date')).exists(): 
        raise serializers.ValidationError('Duplicates for date or datetime not allowed') 
    return data 

但是当我收到 PUT 或 PATCH 请求时,这就变成了一个问题,因为尽管这条记录是表中唯一的记录,但我引发了 ValidationError 恰恰是因为有一条包含此 date-time 对的记录。

覆盖 validate 方法也没有解决阻止从 Django-Admin 创建这样的对的问题。

目前我最接近验证的是使用 MyModel 的 save 方法,但我不明白如何在那里处理这种情况以符合创建/更新流程。

请您参考如下方法:

对于 Django Rest Framework 验证,您可以使用 self.instance 检查来使用不同的验证流程来创建和修改对象;

def validate(self, data): 
    if self.instance: 
        # Modifiying an existing instance, run validations accordingly 
    else: 
        # Creading a new instance, run validations accordingly 

对于管理站点,您可以使用 Django 的 ModelForm 结构及其验证来强制执行管理站点的验证。您需要将您的管理站点设置为使用您的 MyModel

自定义表单