Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/api-guide/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* `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

A floating point representation.
Expand Down
8 changes: 8 additions & 0 deletions docs/api-guide/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,14 @@ When set to `True`, the serializer `DecimalField` class will return strings inst

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
Expand Down
30 changes: 30 additions & 0 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,36 @@ def to_representation(self, 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):
default_error_messages = {
'invalid': _('A valid number is required.'),
Expand Down
5 changes: 3 additions & 2 deletions rest_framework/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
BooleanField, CharField, ChoiceField, DateField, DateTimeField, DecimalField,
DictField, DurationField, EmailField, Field, FileField, FilePathField, FloatField,
HiddenField, HStoreField, IPAddressField, ImageField, IntegerField, JSONField,
ListField, ModelField, MultipleChoiceField, ReadOnlyField,
ListField, ModelField, MultipleChoiceField, ReadOnlyField, BigIntegerField,
RegexField, SerializerMethodField, SlugField, TimeField, URLField, UUIDField,
)
from rest_framework.relations import ( # NOQA # isort:skip
Expand Down Expand Up @@ -906,7 +906,8 @@ class ModelSerializer(Serializer):
"""
serializer_field_mapping = {
models.AutoField: IntegerField,
models.BigIntegerField: IntegerField,
models.BigAutoField: BigIntegerField,
models.BigIntegerField: BigIntegerField,
models.BooleanField: BooleanField,
models.CharField: CharField,
models.CommaSeparatedIntegerField: CharField,
Expand Down
1 change: 1 addition & 0 deletions rest_framework/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
'COMPACT_JSON': True,
'STRICT_JSON': True,
'COERCE_DECIMAL_TO_STRING': True,
'COERCE_BIGINT_TO_STRING': False,
'UPLOADED_FILES_USE_URL': True,

# Browsable API
Expand Down
62 changes: 62 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,68 @@ class TestMinMaxIntegerField(FieldValues):
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):
"""
Valid and invalid values for `FloatField`.
Expand Down
2 changes: 1 addition & 1 deletion tests/test_model_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class Meta:
expected = dedent(r"""
TestSerializer\(\):
auto_field = IntegerField\(read_only=True\)
big_integer_field = IntegerField\(.*\)
big_integer_field = BigIntegerField\(.*\)
boolean_field = BooleanField\(required=False\)
char_field = CharField\(max_length=100\)
comma_separated_integer_field = CharField\(max_length=100, validators=\[<django.core.validators.RegexValidator object>\]\)
Expand Down