Skip to content

Commit 82c9a42

Browse files
committed
Added MaxValueValidator to NumberFilter.
1 parent 2ebce74 commit 82c9a42

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

django_filters/filters.py

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from datetime import timedelta
33

44
from django import forms
5+
from django.core.validators import MaxValueValidator
56
from django.db.models import Q
67
from django.db.models.constants import LOOKUP_SEP
78
from django.forms.utils import pretty_name
@@ -357,6 +358,23 @@ class ModelMultipleChoiceFilter(QuerySetRequestMixin, MultipleChoiceFilter):
357358
class NumberFilter(Filter):
358359
field_class = forms.DecimalField
359360

361+
def get_max_validator(self):
362+
"""
363+
Return a MaxValueValidator for the field, or None to disable.
364+
"""
365+
return MaxValueValidator(1e50)
366+
367+
@property
368+
def field(self):
369+
if not hasattr(self, '_field'):
370+
field = super().field
371+
max_validator = self.get_max_validator()
372+
if max_validator:
373+
field.validators.append(max_validator)
374+
375+
self._field = field
376+
return self._field
377+
360378

361379
class NumericRangeFilter(Filter):
362380
field_class = RangeField

docs/ref/filters.txt

+6
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,12 @@ QuerySet, which then gets used as the model's manager::
426426
Filters based on a numerical value, used with ``IntegerField``, ``FloatField``,
427427
and ``DecimalField`` by default.
428428

429+
.. method:: NumberFilter.get_max_validator()
430+
431+
Return a ``MaxValueValidator`` instance that will be added to
432+
``field.validators``. By default uses a limit value of ``1e50``. Return
433+
``None`` to disable maximum value validation.
434+
429435
``NumericRangeFilter``
430436
~~~~~~~~~~~~~~~~~~~~~~
431437

tests/test_forms.py

+14
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,17 @@ def test_is_bound_and_not_valid(self):
255255
self.assertFalse(f.is_valid())
256256
self.assertEqual(f.data, {'price': 'four dollars'})
257257
self.assertEqual(f.errors, {'price': ['Enter a number.']})
258+
259+
def test_number_filter_max_value_validation(self):
260+
class F(FilterSet):
261+
class Meta:
262+
model = Book
263+
fields = ['average_rating']
264+
265+
f = F({'average_rating': '1E1001'})
266+
self.assertTrue(f.is_bound)
267+
self.assertFalse(f.is_valid())
268+
self.assertEqual(
269+
f.errors,
270+
{'average_rating': ['Ensure this value is less than or equal to 1e+50.']}
271+
)

0 commit comments

Comments
 (0)