如何限制Django模型中数值字段的最大值?
Django有很多种数字类型可以用在模型里,比如DecimalField和PositiveIntegerField。虽然DecimalField可以限制小数点后的位数和总字符数,但有没有办法限制它只能存储某个范围内的数字,比如0.0到5.0之间的数字呢?
如果不能这样做,有没有办法限制PositiveIntegerField只能存储,比如说,最大为50的数字呢?
更新:现在Bug 6845 已经解决,所以这个StackOverflow的问题可能就不再重要了。
10 个回答
在编程中,有时候我们会遇到一些问题,尤其是在使用特定的工具或库时。比如,有人可能在使用某个库的时候,发现它的某些功能没有按照预期工作。这种情况可能会让人感到困惑,因为我们可能不知道问题出在哪里。
通常,解决这类问题的第一步是仔细检查代码,看看有没有写错的地方。接着,可以查阅相关的文档,了解这个库的使用方法和注意事项。如果文档中没有找到答案,可以考虑在网上搜索一下,看看其他人是否遇到过类似的问题。
如果还是找不到解决办法,向社区求助也是一个不错的选择。比如,可以在StackOverflow上发帖,描述你的问题,并附上相关的代码和错误信息。这样,其他有经验的人就能更好地帮助你。
总之,遇到问题时不要慌张,逐步排查,寻找解决方案,通常都能找到答案。
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
size = models.IntegerField(validators=[MinValueValidator(0),
MaxValueValidator(5)])
你可以使用 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
,就不需要这么做,因为表单会自动处理这些验证。
你也可以创建一个自定义的模型字段类型,具体可以参考这个链接: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) - 不过这个想法很有趣...