Django在模型中提供了各种数字字段,例如DecimalField和PositiveIntegerField。虽然前者可以被限制为存储小数点后的位数和存储的字符总数,但是否有办法将其限制为仅存储某个范围内的数字,例如0.0-5.0 ?
如果做不到这一点,有没有办法限制PositiveIntegerField只存储,例如,最多50的数字?
更新:现在Bug 6845已经关闭,这个StackOverflow问题可能是没有意义的。——sampablokuper
Django在模型中提供了各种数字字段,例如DecimalField和PositiveIntegerField。虽然前者可以被限制为存储小数点后的位数和存储的字符总数,但是否有办法将其限制为仅存储某个范围内的数字,例如0.0-5.0 ?
如果做不到这一点,有没有办法限制PositiveIntegerField只存储,例如,最多50的数字?
更新:现在Bug 6845已经关闭,这个StackOverflow问题可能是没有意义的。——sampablokuper
当前回答
如果你想要一些额外的灵活性并且不想改变你的模型字段,下面是最好的解决方案。只需添加这个自定义验证器:
#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)
它可以这样使用:
class YourModel(models.Model):
....
no_dependents = models.PositiveSmallIntegerField("How many dependants?", blank=True, null=True, default=0, validators=[validate_range_or_null(1,100)])
这两个参数是max和min,它允许为空。如果您愿意,您可以通过去掉标记的if语句或将您的字段更改为模型中的blank=False, null=False来定制验证器。这当然需要迁移。
注意:我必须添加验证器,因为Django不验证PositiveSmallIntegerField的范围,而是为这个字段创建一个smallint(在postgres中),如果指定的数字超出了范围,你会得到一个DB错误。
希望这有助于:)更多关于Django中的验证器。
另外,我的答案是基于django.core中的BaseValidator。验证器,但除了代码以外,一切都不同。
其他回答
我也有同样的问题;这是我的解决方案:
SCORE_CHOICES = zip( range(1,n), range(1,n) )
score = models.IntegerField(choices=SCORE_CHOICES, blank=True)
在forms.py中
Class FloatForm(forms.ModelForm):
class Meta:
model = Float
fields = ('name','country', 'city', 'point', 'year')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['point'] = forms.FloatField(max_value=100, min_value=1)
值得一提的是,有时候Django验证并不管用,因为Django验证主要是应用程序级的验证,而不是数据库级的验证。同样,模型验证不会在模型的保存/创建/更新过程中自动运行。如果你想在代码中立即验证你的值,那么你需要手动执行——使用override save()方法:
class UserRating():
SCORE_CHOICES = (
(1, _("Terrible")),
(2, _("Poor")),
(3, _("Average")),
(4, _("Very Good")),
(5, _("Excellent")),
)
score = models.PositiveSmallIntegerField(
choices=SCORE_CHOICES, default=1,
validators=[
MaxValueValidator(5),
MinValueValidator(1)
]
)
def save(self, *args, **kwargs):
if int(self.score) < 1 or int(self.score) > 5:
raise ValidationError('Score must be located between 0 to 5')
super(UserRating, self).save(*args, **kwargs)
...
在models.py中的model列中添加如下验证器
class Planogram(models.Model):
camera = models.ForeignKey(Camera, on_delete=models.CASCADE)
xtl = models.DecimalField(decimal_places=10, max_digits=11,validators=[MaxValueValidator(1),MinValueValidator(0)])
如果你使用create函数来创建对象,将其更改为如下....的构造函数 并在该对象上调用fullclean(),然后保存.. 一切都会完美无缺。
planogram = Planogram(camera_id = camera,xtl=xtl,ytl=ytl,xbr=xbr,ybr=ybr,product_id=product_id)
planogram.full_clean()
planogram.save()
你可以使用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时,这不是必需的,因为表单将自动执行此操作。