Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Override model serializer globally, big integer fieldΒ #9721

Closed
@HoodyH

Description

@HoodyH

First of all thanks for this project, i can't use Django without drf πŸ˜€

Im looking for a way to override serializers.ModelSerializer globally

Little bit of context:
Our application is grown big and we want to switch django backend from BigAutoField to SnowflakeAutoField.

My problem:

  • ts/js (My frontend) do not support numbers over 2^52,
  • I don't want to use Bigint in ts
  • i don't want to touch MAX_SAFE_INTEGER

So the best solution in my opinion is to serialize bigint as string.

class SnowflakeField(serializers.Field):

    def to_representation(self, value):
        return str(value)

    def to_internal_value(self, data):
        try:
            return int(data)
        except ValueError:
            raise serializers.ValidationError("Invalid integer value")

class SnowflakeModelSerializer(serializers.ModelSerializer):
    """
    Snowflake is a bigint so convert to string to avoid frontend memory handling problems
    """
    def build_standard_field(self, field_name, model_field):

        field_class, field_kwargs = super().build_standard_field(field_name, model_field)

        # Use BigIntAsStringField per BigIntegerField
        if isinstance(model_field, models.BigIntegerField):
            field_class = SnowflakeField

        return field_class, field_kwargs

Anyway, since django uses bigint as id, serializing it as sting could be a better option in any case since the id can grow big

Possible ways

  1. use my custom serializer around the code (not so clean)
class MyModelSerializer(SnowflakeModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'
  1. Write a Custom JsonRender and JsonParser

and do something like this with a lot of assumptions, spoiler bad programming

class SnowflakeJSONRenderer(JSONRenderer):

    def _convert_big_integers(self, obj):
        if isinstance(obj, dict):
            return {key: self._convert_big_integers(value) for key, value in obj.items()}
        elif isinstance(obj, list):
            return [self._convert_big_integers(item) for item in obj]
        elif isinstance(obj, int) and obj > 2**53:
            return str(obj)
        return obj

What im looking for

As far as i know there is no option to do this

REST_FRAMEWORK = {
'DEFAULT_MODEL_SERIALIZER_CLASS': 'path.to.utils.serializers.CustomModelSerializer',
}

Am i missing something? In your opinion what could be the best solution? I'm open to any suggestion

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions