Django 有各种可在模型中使用的数字字段,例如 DecimalField 和 PositiveIntegerField。 虽然前者可以限制存储的小数位数和存储的字符总数,但是有没有办法限制它只存储一定范围内的数字,例如0.0-5.0?
如果做不到这一点,是否有任何方法可以限制 PositiveIntegerField 仅存储例如最多 50 的数字?
更新:现在 Bug 6845 已被关闭,此StackOverflow 问题可能没有实际意义。
Django has various numeric fields available for use in models, e.g. DecimalField and PositiveIntegerField. Although the former can be restricted to the number of decimal places stored and the overall number of characters stored, is there any way to restrict it to storing only numbers within a certain range, e.g. 0.0-5.0?
Failing that, is there any way to restrict a PositiveIntegerField to only store, for instance, numbers up to 50?
Update: now that Bug 6845 has been closed, this StackOverflow question may be moot.
发布评论
评论(10)
您可以使用 Django 内置验证器 -
< strong>编辑:直接使用模型时,请确保调用模型full_clean 方法,然后保存模型以触发验证器。 使用 ModelForm 时不需要这样做,因为表单会自动执行此操作。
You can use Django's built-in validators—
Edit: When working directly with the model, make sure to call the model full_clean method before saving the model in order to trigger the validators. This is not required when using
ModelForm
since the forms will do that automatically.您还可以创建自定义模型字段类型 - 请参阅 http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields
在这种情况下,您可以从内置中“继承” IntegerField 并覆盖其验证逻辑。
我想得越多,我就越意识到这对于许多 Django 应用程序来说是多么有用。 也许 IntegerRangeField 类型可以作为补丁提交,供 Django 开发人员考虑添加到主干。
这对我有用:
然后在您的模型类中,您将像这样使用它(字段是您放置上述代码的模块):
或者对于负值和正值范围(如振荡器范围):
真正的是什么如果可以像这样使用范围运算符调用它,那就很酷了:
但是,这将需要更多代码,因为您可以指定“跳过”参数 - range(1, 50, 2) - 不过有趣的想法......
You could also create a custom model field type - see http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields
In this case, you could 'inherit' from the built-in IntegerField and override its validation logic.
The more I think about this, I realize how useful this would be for many Django apps. Perhaps a IntegerRangeField type could be submitted as a patch for the Django devs to consider adding to trunk.
This is working for me:
Then in your model class, you would use it like this (field being the module where you put the above code):
OR for a range of negative and positive (like an oscillator range):
What would be really cool is if it could be called with the range operator like this:
But, that would require a lot more code since since you can specify a 'skip' parameter - range(1, 50, 2) - Interesting idea though...
我也遇到了同样的问题; 这是我的解决方案:
I had this very same problem; here was my solution:
有两种方法可以做到这一点。 一是使用表单验证,绝不让用户输入任何超过 50 的数字。 表单验证文档。
如果没有用户参与该过程,或者您没有使用表单输入数据,那么您必须重写模型的
save
方法以引发异常或限制数据进入场。There are two ways to do this. One is to use form validation to never let any number over 50 be entered by a user. Form validation docs.
If there is no user involved in the process, or you're not using a form to enter data, then you'll have to override the model's
save
method to throw an exception or limit the data going into the field.如果您想要一些额外的灵活性并且不想更改模型字段,这是最好的解决方案。 只需添加这个自定义验证器:
它可以这样使用:
两个参数是 max 和 min,并且它允许 null。 如果您愿意,您可以通过删除标记的 if 语句或将模型中的字段更改为空白=False、null=False 来自定义验证器。 这当然需要迁移。
注意:我必须添加验证器,因为 Django 不会验证 PositiveSmallIntegerField 上的范围,而是为此字段创建一个smallint(在 postgres 中),如果指定的数字超出范围,您会收到数据库错误。
希望这会有所帮助:) 有关 Django 中的验证器 的更多信息。
附言。 我的答案基于 django.core.validators 中的 BaseValidator,但除了代码之外,一切都不同。
Here is the best solution if you want some extra flexibility and don't want to change your model field. Just add this custom validator:
And it can be used as such:
The two parameters are max and min, and it allows nulls. You can customize the validator if you like by getting rid of the marked if statement or change your field to be blank=False, null=False in the model. That will of course require a migration.
Note: I had to add the validator because Django does not validate the range on PositiveSmallIntegerField, instead it creates a smallint (in postgres) for this field and you get a DB error if the numeric specified is out of range.
Hope this helps :) More on Validators in Django.
PS. I based my answer on BaseValidator in django.core.validators, but everything is different except for the code.
例如,您可以使用 MaxValueValidator() 和 MinValueValidator() 对于 models.DecimalField() 和 models.PositiveIntegerField() 设置值的可用范围如下所示:
最后,最好重写
num1 和
num2
字段与 表单。 DecimalField() 和 forms.IntegerField() 设置 Django Admin 中值的可用范围,如下所示:另外,代码中带有 forms.NumberInput 与上面的代码相同:
For example, you can use MaxValueValidator() and MinValueValidator() for models.DecimalField() and models.PositiveIntegerField() to set the available range of the value as shown below:
Finally, you better override
num1
andnum2
fields with forms.DecimalField() and forms.IntegerField() to set the available range of the value in Django Admin as shown below:In addition, the code with forms.NumberInput below is identical to the code above:
在 forms.py 中
In the forms.py
值得一提的是,有时 Django 验证不起作用,因为 Django 验证主要是应用程序级别的验证,而不是数据库级别的验证。 此外,模型验证不会在模型的保存/创建/更新时自动运行。 如果您想在代码中立即验证您的值,那么您需要手动执行此操作 - 使用覆盖
save()
方法:It is worth mentioning that sometimes Django validation doesn't work as Django validation is mostly an application-level validation, not validation at the database level. Also, Model validation is not run automatically on the save/create/update of the model. If you want to validate your values instantly in your code then you need to do it manually — using the override
save()
method:在 models.py 中的模型列中添加这样的验证器,
如果您使用 create 函数来创建对象,则 将其更改为构造函数,如下所示......
并对该对象调用 fullclean() 然后保存..
一切都会完美地进行。
Add validator like this your model column in models.py
if you are using create function to create objects change it to constructor like below....
and call fullclean() on that object and then save..
everything will work perfectly.