我在我的 Django 模型中存储了一些浮点数据,并且只有一定范围的值是有意义的。因此,我想在模型和 SQL 约束级别施加这些限制。
例如,我想做这样的事情:
class Foo(Model):
myfloat = FloatField(min=0.0, max=1.0)
我想在模型级别而不是表单级别执行此操作。实际上,我可能希望表单级别具有不同的范围;例如,在表单级别使用百分比 [0,100],但在模型中转换为 [0,1]。
这是可能的,如果是这样,我将如何去做?
我在我的 Django 模型中存储了一些浮点数据,并且只有一定范围的值是有意义的。因此,我想在模型和 SQL 约束级别施加这些限制。
例如,我想做这样的事情:
class Foo(Model):
myfloat = FloatField(min=0.0, max=1.0)
我想在模型级别而不是表单级别执行此操作。实际上,我可能希望表单级别具有不同的范围;例如,在表单级别使用百分比 [0,100],但在模型中转换为 [0,1]。
这是可能的,如果是这样,我将如何去做?
到目前为止的答案描述了如何使表单验证。您还可以将验证器放入模型中。使用MinValueValidator和MaxValueValidator。
例如:
from django.core.validators import MaxValueValidator, MinValueValidator
...
weight = models.FloatField(
validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
)
编辑:
但是,这不会添加 SQL 约束。
您可以添加 SQL 约束,如此处所述的sCheckConstraint
in Meta.constraints
。
组合示例:
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db.models import CheckConstraint, Q
class Foo(Model):
myfloat = FloatField(min=0.0, max=1.0,
# for checking in forms
validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],)
class Meta:
constraints = (
# for checking in the DB
CheckConstraint(
check=Q(myfloat__gte=0.0) & Q(myfloat__lte=1.0),
name='foo_myfloat_range'),
)
如果您需要对表单级别进行限制,您可以传递min_value
并传递max_value
到表单字段:
myfloat = forms.FloatField(min_value=0.0, max_value=1.0)
但是,如果您需要将其提升到模型级别,则必须扩展基models.FloatField
类
class MinMaxFloat(models.FloatField):
def __init__(self, min_value=None, max_value=None, *args, **kwargs):
self.min_value, self.max_value = min_value, max_value
super(MinMaxFloat, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
defaults = {'min_value': self.min_value, 'max_value' : self.max_value}
defaults.update(kwargs)
return super(MinMaxFloat, self).formfield(**defaults)
然后你可以在模型中使用它
class Foo(models.Model):
myfloat = MinMaxFloat(min_value=0.0, max_value=1.0)
已经有一段时间了,社区投票的答案已经足够好,基于 Django 内置,但这里有另一种方法,具体问题,遵循Django 项目的文档。
# app/models.py or create another file for custom validators, i.e. app/custom_validators.py
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ # use if you support internationalization
def validate_interval(value):
if value < 0.0 or value > 1.0:
raise ValidationError(_('%(value)s must be in the range [0.0, 1.0]'), params={'value': value},)
# app/models.py
class Foo(models.Model):
myfloat = models.FloatField(validators=[validate_interval])
您甚至可以使验证器参数更通用。
请记住,在表单的clean()
方法期间调用任何验证器。
IE 如果您尝试直接创建对象而不使用表单,则不会调用您的验证器。
有些人不推荐它,但如果您想在创建对象时调用验证器,请覆盖 save 方法。
# app/models.py
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ # use if you support internationalization
class Foo(models.Model):
def save(self, *args, **kwargs):
self.full_clean() # or clean
super().save(*args, **kwargs)
def validate_interval(value):
if value < 0.0 or value > 1.0:
raise ValidationError(_('%(value)s must be in the range [0.0, 1.0]'), params={'value': value},)
myfloat = models.FloatField(validators=[validate_interval])