sam*_*per 144 python django numbers django-models
Django有各种可用于模型的数字字段,例如DecimalField和PositiveIntegerField.虽然前者可以限制在存储小数位的数量和字符的存储总数,有没有办法将其限制于存储只在一定范围内的数字,如0.0-5.0?
如果失败了,有没有办法限制一个PositiveIntegerField只存储,例如,最多50个数字?
更新:现在Bug 6845 已经关闭,这个StackOverflow问题可能没什么问题. - sampablokuper
use*_*050 293
你可以使用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)
]
)
Run Code Online (Sandbox Code Playgroud)
编辑:虽然这些仅在您在ModelForm中使用模型时有效,但如果您" 单独使用"模型,则不会感叹.
Nat*_*anD 127
您还可以创建自定义模型字段类型 - 请参阅http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields
在这种情况下,您可以从内置的IntegerField"继承"并覆盖其验证逻辑.
我越是想到这一点,我意识到这对许多Django应用程序有多大用处.也许IntegerRangeField类型可以作为Django开发者考虑添加到trunk的补丁提交.
这对我有用:
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)
Run Code Online (Sandbox Code Playgroud)
然后在你的模型类中,你会像这样使用它(字段是放置上面代码的模块):
size = fields.IntegerRangeField(min_value=1, max_value=50)
Run Code Online (Sandbox Code Playgroud)
或者对于一系列的负面和正面(如振荡器范围):
size = fields.IntegerRangeField(min_value=-100, max_value=100)
Run Code Online (Sandbox Code Playgroud)
如果可以使用范围运算符调用它,那真的很酷:
size = fields.IntegerRangeField(range(1, 50))
Run Code Online (Sandbox Code Playgroud)
但是,这需要更多代码,因为你可以指定'skip'参数 - 范围(1,50,2) - 尽管有趣的想法......
小智 70
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
size = models.IntegerField(validators=[MinValueValidator(0),
MaxValueValidator(5)])
Run Code Online (Sandbox Code Playgroud)
小智 50
我有同样的问题; 这是我的解决方案:
SCORE_CHOICES = zip( range(1,n), range(1,n) )
score = models.IntegerField(choices=SCORE_CHOICES, blank=True)
Run Code Online (Sandbox Code Playgroud)
如果您想要一些额外的灵活性并且不想更改模型字段,这是最好的解决方案。只需添加此自定义验证器:
#Imports
from django.core.exceptions import ValidationError
class validate_range_or_null(object):
compare = lambda self, a, b, c: a > c or a < b
clean = lambda self, x: x
message = ('Ensure this value is between %(limit_min)s and %(limit_max)s (it is %(show_value)s).')
code = 'limit_value'
def __init__(self, limit_min, limit_max):
self.limit_min = limit_min
self.limit_max = limit_max
def __call__(self, value):
cleaned = self.clean(value)
params = {'limit_min': self.limit_min, 'limit_max': self.limit_max, 'show_value': cleaned}
if value: # make it optional, remove it to make required, or make required on the model
if self.compare(cleaned, self.limit_min, self.limit_max):
raise ValidationError(self.message, code=self.code, params=params)
Run Code Online (Sandbox Code Playgroud)
它可以这样使用:
class YourModel(models.Model):
....
no_dependents = models.PositiveSmallIntegerField("How many dependants?", blank=True, null=True, default=0, validators=[validate_range_or_null(1,100)])
Run Code Online (Sandbox Code Playgroud)
两个参数是max和min,它允许为空。您可以根据需要通过删除标记的if语句来自定义验证器,或者在模型中将字段更改为blank = False,null = False。当然,这将需要迁移。
注意:我必须添加验证器,因为Django不会验证PositiveSmallIntegerField上的范围,而是会为此字段创建一个smallint(在postgres中),并且如果指定的数字超出范围,则会出现DB错误。
希望对您有所帮助:)有关Django中的Validators的更多信息。
PS。我的答案基于django.core.validators中的BaseValidator,但除代码外,其他所有内容都不同。