-
-
Notifications
You must be signed in to change notification settings - Fork 7k
min_value/max_value support in DurationField #5643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Can't we rather use validators ? |
That's what the existing code in integer/float/decimal already used. I just moved it to a base class. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting the validators generation is a nice move.
OTOH I'm not sure I prefer
DurationField(min_value=datetime.timedelta(days=1), max_value=datetime.timedelta(days=4))
over
DurationField(validators=[MinValueValidator(datetime.timedelta(days=1), message=message), MaxValueValidator(datetime.timedelta(days=4), message=message)])
rest_framework/fields.py
Outdated
'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'), | ||
'max_decimal_places': _('Ensure that there are no more than {max_decimal_places} decimal places.'), | ||
'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'), | ||
'max_string_length': _('String value too large.') | ||
} | ||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs. | ||
|
||
def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None, | ||
def __init__(self, max_digits, decimal_places, coerce_to_string=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an API change. I'd rather keep the current signature as it is.
rest_framework/fields.py
Outdated
@@ -903,20 +903,16 @@ def to_internal_value(self, data): | |||
|
|||
# Number types... | |||
|
|||
class IntegerField(Field): | |||
class _MaxMinValueField(Field): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather it be a MaxMinMixin
instead of a base class.
IMHO, you can say the same about |
agreed, which is why I haven't closed it already :) |
Let me put it this way: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm +1 on adding min/max handling to DurationField
. Also a +1 on factoring out the relevant min/max validation handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an extra part to this. In rest_framework.utils.field_mapping.get_field_kwargs
, do we want to be ensuring max_value
and min_value
are passed as kwargs rather than validators, as we do for other fields?
django-rest-framework/rest_framework/utils/field_mapping.py
Lines 128 to 152 in daba5e9
# Ensure that max_value is passed explicitly as a keyword arg, | |
# rather than as a validator. | |
max_value = next(( | |
validator.limit_value for validator in validator_kwarg | |
if isinstance(validator, validators.MaxValueValidator) | |
), None) | |
if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): | |
kwargs['max_value'] = max_value | |
validator_kwarg = [ | |
validator for validator in validator_kwarg | |
if not isinstance(validator, validators.MaxValueValidator) | |
] | |
# Ensure that min_value is passed explicitly as a keyword arg, | |
# rather than as a validator. | |
min_value = next(( | |
validator.limit_value for validator in validator_kwarg | |
if isinstance(validator, validators.MinValueValidator) | |
), None) | |
if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): | |
kwargs['min_value'] = min_value | |
validator_kwarg = [ | |
validator for validator in validator_kwarg | |
if not isinstance(validator, validators.MinValueValidator) | |
] |
(Not yet sure what I think about the change in general: if we go for it the proposed changes seem OK.)
be1c751
to
e32736d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @noamkush. This looks great.
IMHO, you can say the same about FloatField, I don't see the difference.
I think this is what swings it. 🙂
I've squashed your commits and added DurationField
to have the min/max kwargs set from any validators in field_mapping
. (This is the same as we apply to the other numeric fields.)
Please take a look to make sure it looks as expected.
Thanks for the effort!
e32736d
to
77200f6
Compare
Looks great to me |
rest_framework/fields.py
Outdated
@@ -903,20 +903,16 @@ def to_internal_value(self, data): | |||
|
|||
# Number types... | |||
|
|||
class IntegerField(Field): | |||
class MaxMinMixin(object): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please let's not push behavior into mixin classes.
I'm okay with us adding this behavior in, but I'd rather we replicated code than used mixin classes. |
Hi @noamkush — fancy pulling out the mixin and just applying the change to |
…hem to DurationField. PR fixes. Python 2 fix.
77200f6
to
4537444
Compare
I rebased and pulled out the mixin. We'll take this now. Thanks for the input @noamkush! |
* Added min_value/max_value field arguments to DurationField. * Made field mapping use mix/max kwargs for DurationField validators.
This adds min_value/max_value to DurationField, by splitting the code for min_value/max_value from Integer/Float/Decimal fields into a shared base class and having DurationField also inherit it.
I think it's useful for cases such as accepting only positive/negative durations or accepting at least a minute, at least an hour etc.