如何创建具有最大和最小限制的Django FloatField?

时间:2012-05-10 17:10:54

标签: django django-models

我在我的Django模型中存储了一些浮点数据,只有一定范围的值才有意义。因此,我想在模型和SQL约束级别强加这些限制。

例如,我想做这样的事情:

class Foo(Model):
   myfloat = FloatField(min=0.0, max=1.0)

我想在模型级别而不是表单级别执行此操作。事实上,我可能希望表单级别具有不同的范围;例如,在表单级别使用百分比[0,100],但在模型中转换为[0,1]。

这是可能的,如果可以的话,我该怎么做呢?

3 个答案:

答案 0 :(得分:92)

到目前为止,答案描述了如何使表单验证。您还可以在模型中放置验证器。使用MinValueValidatorMaxValueValidator

例如:

from django.core.validators import MaxValueValidator, MinValueValidator

...
weight = models.FloatField(
    validators=[MinValueValidator(0.9), MaxValueValidator(58)],
)

我认为不会增加SQL约束,等等。

答案 1 :(得分:14)

如果您需要在表单级别设置约束,则可以将min_valuemax_value传递给form field

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)

答案 2 :(得分:0)

已经有一段时间了,社区投票的答案已经足够好,基于 Django 内置程序,但这里有另一种方法,特定于问题,遵循 Django Project's documentation

创建自定义验证器

# 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() 方法期间调用的。

I.E.如果您尝试不使用表单直接创建对象,您的验证器将不会被调用。

有些人不推荐它,但如果您想在创建对象时调用验证器,请重写 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])