mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-09-16 01:02:29 +03:00
feat: BinIntegerField and COERCE_BIGINT_TO_STRING setting, bigint now can have string api representation
This commit is contained in:
parent
1472848501
commit
62335cfaf9
|
@ -269,6 +269,18 @@ Corresponds to `django.db.models.fields.IntegerField`, `django.db.models.fields.
|
||||||
* `max_value` Validate that the number provided is no greater than this value.
|
* `max_value` Validate that the number provided is no greater than this value.
|
||||||
* `min_value` Validate that the number provided is no less than this value.
|
* `min_value` Validate that the number provided is no less than this value.
|
||||||
|
|
||||||
|
## BigIntegerField
|
||||||
|
|
||||||
|
An biginteger representation.
|
||||||
|
|
||||||
|
Corresponds to `django.db.models.fields.BigIntegerField`.
|
||||||
|
|
||||||
|
**Signature**: `BigIntegerField(max_value=None, min_value=None, coerce_to_string=None)`
|
||||||
|
|
||||||
|
* `max_value` Validate that the number provided is no greater than this value.
|
||||||
|
* `min_value` Validate that the number provided is no less than this value.
|
||||||
|
* `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `BigInteger` objects should be returned. Defaults to the same value as the `COERCE_BIGINT_TO_STRING` settings key, which will be `True` unless overridden. If `BigInterger` objects are returned by the serializer, then the final output format will be determined by the renderer.
|
||||||
|
|
||||||
## FloatField
|
## FloatField
|
||||||
|
|
||||||
A floating point representation.
|
A floating point representation.
|
||||||
|
|
|
@ -371,6 +371,14 @@ When set to `True`, the serializer `DecimalField` class will return strings inst
|
||||||
|
|
||||||
Default: `True`
|
Default: `True`
|
||||||
|
|
||||||
|
#### COERCE_BIGINT_TO_STRING
|
||||||
|
|
||||||
|
When returning biginteger objects in API representations that do not support numbers up to 2^64, it is best to return the value as a string. This avoids the loss of precision that occurs with biginteger implementations.
|
||||||
|
|
||||||
|
When set to `True`, the serializer `BigIntegerField` class will return strings instead of `BigInteger` objects. When set to `False`, serializers will return `BigInteger` objects, which the default JSON encoder will return as numbers.
|
||||||
|
|
||||||
|
Default: `False`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## View names and descriptions
|
## View names and descriptions
|
||||||
|
|
|
@ -921,6 +921,36 @@ class IntegerField(Field):
|
||||||
return int(value)
|
return int(value)
|
||||||
|
|
||||||
|
|
||||||
|
class BigIntegerField(IntegerField):
|
||||||
|
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _('A valid biginteger is required.'),
|
||||||
|
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
||||||
|
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
||||||
|
'max_string_length': _('String value too large.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, coerce_to_string=None, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
if coerce_to_string is not None:
|
||||||
|
self.coerce_to_string = coerce_to_string
|
||||||
|
|
||||||
|
def to_representation(self, value):
|
||||||
|
coerce_to_string = getattr(self, 'coerce_to_string', api_settings.COERCE_BIGINT_TO_STRING)
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
if coerce_to_string:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if coerce_to_string:
|
||||||
|
return str(value)
|
||||||
|
else:
|
||||||
|
return int(value)
|
||||||
|
|
||||||
|
|
||||||
class FloatField(Field):
|
class FloatField(Field):
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _('A valid number is required.'),
|
'invalid': _('A valid number is required.'),
|
||||||
|
|
|
@ -30,7 +30,7 @@ from rest_framework.compat import (
|
||||||
get_referenced_base_fields_from_q, postgres_fields
|
get_referenced_base_fields_from_q, postgres_fields
|
||||||
)
|
)
|
||||||
from rest_framework.exceptions import ErrorDetail, ValidationError
|
from rest_framework.exceptions import ErrorDetail, ValidationError
|
||||||
from rest_framework.fields import get_error_detail
|
from rest_framework.fields import get_error_detail, BigIntegerField
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.utils import html, model_meta, representation
|
from rest_framework.utils import html, model_meta, representation
|
||||||
from rest_framework.utils.field_mapping import (
|
from rest_framework.utils.field_mapping import (
|
||||||
|
@ -906,7 +906,8 @@ class ModelSerializer(Serializer):
|
||||||
"""
|
"""
|
||||||
serializer_field_mapping = {
|
serializer_field_mapping = {
|
||||||
models.AutoField: IntegerField,
|
models.AutoField: IntegerField,
|
||||||
models.BigIntegerField: IntegerField,
|
models.BigAutoField: BigIntegerField,
|
||||||
|
models.BigIntegerField: BigIntegerField,
|
||||||
models.BooleanField: BooleanField,
|
models.BooleanField: BooleanField,
|
||||||
models.CharField: CharField,
|
models.CharField: CharField,
|
||||||
models.CommaSeparatedIntegerField: CharField,
|
models.CommaSeparatedIntegerField: CharField,
|
||||||
|
|
|
@ -116,6 +116,7 @@ DEFAULTS = {
|
||||||
'COMPACT_JSON': True,
|
'COMPACT_JSON': True,
|
||||||
'STRICT_JSON': True,
|
'STRICT_JSON': True,
|
||||||
'COERCE_DECIMAL_TO_STRING': True,
|
'COERCE_DECIMAL_TO_STRING': True,
|
||||||
|
'COERCE_BIGINT_TO_STRING': False,
|
||||||
'UPLOADED_FILES_USE_URL': True,
|
'UPLOADED_FILES_USE_URL': True,
|
||||||
|
|
||||||
# Browsable API
|
# Browsable API
|
||||||
|
|
|
@ -1099,6 +1099,68 @@ class TestMinMaxIntegerField(FieldValues):
|
||||||
field = serializers.IntegerField(min_value=1, max_value=3)
|
field = serializers.IntegerField(min_value=1, max_value=3)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBigIntegerField(FieldValues):
|
||||||
|
"""
|
||||||
|
Valid and invalid values for `BigIntegerField`.
|
||||||
|
"""
|
||||||
|
valid_inputs = {
|
||||||
|
'1': 1,
|
||||||
|
'0': 0,
|
||||||
|
1: 1,
|
||||||
|
0: 0,
|
||||||
|
123: 123,
|
||||||
|
-123: -123,
|
||||||
|
'999999999999999999999999999': 999999999999999999999999999,
|
||||||
|
-999999999999999999999999999: -999999999999999999999999999,
|
||||||
|
1.0: 1,
|
||||||
|
0.0: 0,
|
||||||
|
'1.0': 1
|
||||||
|
}
|
||||||
|
invalid_inputs = {
|
||||||
|
0.5: ['A valid biginteger is required.'],
|
||||||
|
'abc': ['A valid biginteger is required.'],
|
||||||
|
'0.5': ['A valid biginteger is required.']
|
||||||
|
}
|
||||||
|
outputs = {
|
||||||
|
'1': 1,
|
||||||
|
'0': 0,
|
||||||
|
1: 1,
|
||||||
|
0: 0,
|
||||||
|
1.0: 1,
|
||||||
|
0.0: 0,
|
||||||
|
'999999999999999999999999999': 999999999999999999999999999,
|
||||||
|
-999999999999999999999999999: -999999999999999999999999999
|
||||||
|
}
|
||||||
|
field = serializers.BigIntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
class TestMinMaxBigIntegerField(FieldValues):
|
||||||
|
"""
|
||||||
|
Valid and invalid values for `IntegerField` with min and max limits.
|
||||||
|
"""
|
||||||
|
valid_inputs = {
|
||||||
|
'1': 1,
|
||||||
|
'3': 3,
|
||||||
|
1: 1,
|
||||||
|
3: 3,
|
||||||
|
}
|
||||||
|
invalid_inputs = {
|
||||||
|
0: ['Ensure this value is greater than or equal to 1.'],
|
||||||
|
4: ['Ensure this value is less than or equal to 3.'],
|
||||||
|
'0': ['Ensure this value is greater than or equal to 1.'],
|
||||||
|
'4': ['Ensure this value is less than or equal to 3.'],
|
||||||
|
}
|
||||||
|
outputs = {}
|
||||||
|
field = serializers.BigIntegerField(min_value=1, max_value=3)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCoercionBigIntegerField(TestCase):
|
||||||
|
|
||||||
|
def test_force_coerce_to_string(self):
|
||||||
|
field = serializers.BigIntegerField(coerce_to_string=True)
|
||||||
|
assert isinstance(field.to_representation(int('1')), str)
|
||||||
|
|
||||||
|
|
||||||
class TestFloatField(FieldValues):
|
class TestFloatField(FieldValues):
|
||||||
"""
|
"""
|
||||||
Valid and invalid values for `FloatField`.
|
Valid and invalid values for `FloatField`.
|
||||||
|
|
|
@ -171,7 +171,7 @@ class TestRegularFieldMappings(TestCase):
|
||||||
expected = dedent(r"""
|
expected = dedent(r"""
|
||||||
TestSerializer\(\):
|
TestSerializer\(\):
|
||||||
auto_field = IntegerField\(read_only=True\)
|
auto_field = IntegerField\(read_only=True\)
|
||||||
big_integer_field = IntegerField\(.*\)
|
big_integer_field = BigIntegerField\(.*\)
|
||||||
boolean_field = BooleanField\(required=False\)
|
boolean_field = BooleanField\(required=False\)
|
||||||
char_field = CharField\(max_length=100\)
|
char_field = CharField\(max_length=100\)
|
||||||
comma_separated_integer_field = CharField\(max_length=100, validators=\[<django.core.validators.RegexValidator object>\]\)
|
comma_separated_integer_field = CharField\(max_length=100, validators=\[<django.core.validators.RegexValidator object>\]\)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user