如何限制Django模型中数值字段的最大值?

226 投票
10 回答
239490 浏览
提问于 2025-04-15 11:31

Django有很多种数字类型可以用在模型里,比如DecimalFieldPositiveIntegerField。虽然DecimalField可以限制小数点后的位数和总字符数,但有没有办法限制它只能存储某个范围内的数字,比如0.0到5.0之间的数字呢?

如果不能这样做,有没有办法限制PositiveIntegerField只能存储,比如说,最大为50的数字呢?

更新:现在Bug 6845 已经解决,所以这个StackOverflow的问题可能就不再重要了。

10 个回答

106

在编程中,有时候我们会遇到一些问题,尤其是在使用特定的工具或库时。比如,有人可能在使用某个库的时候,发现它的某些功能没有按照预期工作。这种情况可能会让人感到困惑,因为我们可能不知道问题出在哪里。

通常,解决这类问题的第一步是仔细检查代码,看看有没有写错的地方。接着,可以查阅相关的文档,了解这个库的使用方法和注意事项。如果文档中没有找到答案,可以考虑在网上搜索一下,看看其他人是否遇到过类似的问题。

如果还是找不到解决办法,向社区求助也是一个不错的选择。比如,可以在StackOverflow上发帖,描述你的问题,并附上相关的代码和错误信息。这样,其他有经验的人就能更好地帮助你。

总之,遇到问题时不要慌张,逐步排查,寻找解决方案,通常都能找到答案。

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator

size = models.IntegerField(validators=[MinValueValidator(0),
                                       MaxValueValidator(5)])
507

你可以使用 Django自带的验证器——

from django.db.models import IntegerField, Model
from django.core.validators import MaxValueValidator, MinValueValidator

class CoolModelBro(Model):
    limited_integer_field = IntegerField(
        default=1,
        validators=[
            MaxValueValidator(100),
            MinValueValidator(1)
        ]
     )

补充说明: 当你直接操作模型时,记得在保存模型之前调用模型的 full_clean 方法,这样才能触发验证器的检查。如果你使用的是 ModelForm,就不需要这么做,因为表单会自动处理这些验证。

147

你也可以创建一个自定义的模型字段类型,具体可以参考这个链接:http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

在这种情况下,你可以“继承”内置的整数字段(IntegerField),并重写它的验证逻辑。

越想越觉得,这对很多Django应用来说会非常有用。也许可以考虑提交一个整数范围字段(IntegerRangeField)的补丁,让Django的开发者考虑加入到主版本中。

这个方法对我有效:

from django.db import models

class IntegerRangeField(models.IntegerField):
    def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
        self.min_value, self.max_value = min_value, max_value
        models.IntegerField.__init__(self, verbose_name, name, **kwargs)
    def formfield(self, **kwargs):
        defaults = {'min_value': self.min_value, 'max_value':self.max_value}
        defaults.update(kwargs)
        return super(IntegerRangeField, self).formfield(**defaults)

然后在你的模型类中,你可以这样使用它(field是你放置上述代码的模块):

size = fields.IntegerRangeField(min_value=1, max_value=50)

或者用于负数和正数的范围(就像一个振荡器的范围):

size = fields.IntegerRangeField(min_value=-100, max_value=100)

如果能用范围操作符这样调用就更酷了:

size = fields.IntegerRangeField(range(1, 50))

不过,这需要更多的代码,因为你可以指定一个“跳过”参数 - 比如range(1, 50, 2) - 不过这个想法很有趣...

撰写回答