Skip to content

Commit

Permalink
Added MaxValueValidator to NumberFilter.
Browse files Browse the repository at this point in the history
  • Loading branch information
carltongibson committed Sep 26, 2020
1 parent 2ebce74 commit 82c9a42
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
18 changes: 18 additions & 0 deletions django_filters/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta

from django import forms
from django.core.validators import MaxValueValidator
from django.db.models import Q
from django.db.models.constants import LOOKUP_SEP
from django.forms.utils import pretty_name
Expand Down Expand Up @@ -357,6 +358,23 @@ class ModelMultipleChoiceFilter(QuerySetRequestMixin, MultipleChoiceFilter):
class NumberFilter(Filter):
field_class = forms.DecimalField

def get_max_validator(self):
"""
Return a MaxValueValidator for the field, or None to disable.
"""
return MaxValueValidator(1e50)

@property
def field(self):
if not hasattr(self, '_field'):
field = super().field
max_validator = self.get_max_validator()
if max_validator:
field.validators.append(max_validator)

self._field = field
return self._field


class NumericRangeFilter(Filter):
field_class = RangeField
Expand Down
6 changes: 6 additions & 0 deletions docs/ref/filters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ QuerySet, which then gets used as the model's manager::
Filters based on a numerical value, used with ``IntegerField``, ``FloatField``,
and ``DecimalField`` by default.

.. method:: NumberFilter.get_max_validator()

Return a ``MaxValueValidator`` instance that will be added to
``field.validators``. By default uses a limit value of ``1e50``. Return
``None`` to disable maximum value validation.

``NumericRangeFilter``
~~~~~~~~~~~~~~~~~~~~~~

Expand Down
14 changes: 14 additions & 0 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,17 @@ def test_is_bound_and_not_valid(self):
self.assertFalse(f.is_valid())
self.assertEqual(f.data, {'price': 'four dollars'})
self.assertEqual(f.errors, {'price': ['Enter a number.']})

def test_number_filter_max_value_validation(self):
class F(FilterSet):
class Meta:
model = Book
fields = ['average_rating']

f = F({'average_rating': '1E1001'})
self.assertTrue(f.is_bound)
self.assertFalse(f.is_valid())
self.assertEqual(
f.errors,
{'average_rating': ['Ensure this value is less than or equal to 1e+50.']}
)

0 comments on commit 82c9a42

Please sign in to comment.