【问题标题】:Django Model validation based on a field value of another Model基于另一个模型的字段值的 Django 模型验证
【发布时间】:2020-06-23 10:30:27
【问题描述】:

我有这个 Django 模型:

   from accounts.models import Account
   

   class BankOperation(models.Model):
    
       created_at = models.DateTimeField(auto_now_add=True)
       account = models.ForeignKey(Account, on_delete=models.CASCADE)
       operation_import = models.FloatField(default=0.0)
    
    

我想确保operation_import 不高于account.balance 官方的方法是什么?我已经看到一些关于覆盖 save() 方法的答案,但其他人建议不要这样做。

我应该添加一个预保存信号并抛出某种异常吗?

有没有办法创建一个接受参数的字段验证器? 所以可能是这样的:

   def validate_bank_operation_import(value, account_balance):

   if value > account_balance:

        raise ValidationError("Bank operation import is higher than account balance!")

在我的模型中,我将字段更改为:

operation_import = models.FloatField(default=0.0, validators=[validate_bank_operation_import])

但是我可以将参数传递给验证器吗?如果是,我该怎么做?

也许还有其他人来做这个验证!

【问题讨论】:

  • 我不知道谁“建议”不要覆盖Model.save(),但这完全是废话。甚至the doc explicitely tells it's ok:“如果你想要自定义保存行为,你可以重写这个save()方法”

标签: django django-models django-signals django-validation


【解决方案1】:

Override clean on the model? 验证过程在文档中有详细描述,其中包括使用该方法实现自定义验证。因为它是一个绑定方法,所以它可以访问selfself.account.balance

【讨论】:

  • 谢谢!我认为答案会覆盖一种方法,但我自己找不到。你能告诉我应该在哪里调用 clean() 方法吗?在文档中它说:但是,请注意,与 Model.full_clean() 一样,当您调用模型的 save() 方法时,不会调用模型的 clean() 方法。
  • 像这样覆盖 save() 方法是一种好习惯:我应该调用 full_clean() 还是直接 clean() ? def save(self, *args, **kwargs): self.full_clean() return super(BankOperation, self).save(*args, **kwargs)
  • 显然即使不调用 save() 方法也能正常工作。覆盖 clean() 方法现在似乎工作得很好。谢谢你的回答
  • 我想不出任何情况下,重写一个方法然后返回调用其超类的结果,与在调用非对象实例之前立即从外部对对象实例执行相同操作不同直接重写方法。
  • As mentionned in the doc(你真的应该阅读),“当你使用 ModelForm 时,对 is_valid() 的调用将对表单中包含的所有字段执行这些验证步骤”
猜你喜欢
  • 1970-01-01
  • 2015-09-26
  • 2017-02-28
  • 2021-10-09
  • 2011-05-21
  • 2014-12-25
  • 1970-01-01
  • 2019-03-11
  • 2019-12-24
相关资源
最近更新 更多