Django REST framework (DRF) において、DecimalFieldから末尾のゼロを除去する方法です。具体的には以下のように挙動を変更します。
# 現在 Decimal('0.001000000') >> "0.001000000" # 期待する結果 Decimal('0.001000000') >> "0.001"
この機能は以下のPRで追加されましたが、まだリリースされていません。
・ normalize_output
Will normalize the decimal value when serialized. This will strip all trailing zeroes and change the value's precision to the minimum required precision to be able to represent the value without loosing data. Defaults to False.
また、この機能は DecimalField(normalize_output=True)
で有効になるため、全体への適用には少々手間がかかります。
そこで、settingsの拡張を提案しましたが、現在DRFはメンテナンスフェーズ*1にあるため、提案は採用されませんでした。
そこで、#6514の変更を参考に、 quantized.normalize()
を追加したカスタムフィールドを作成しました。
このカスタムフィールドを ModelSerializer.serializer_field_mapping
で models.DecimalField
にマッピングすることで、カスタムフィールドを標準適用します。
(COERCE_DECIMAL_TO_STRING関連の処理は使わないので削っています。)
import decimal from django.db import models from django.utils.formats import localize_input from rest_framework import serializers class NormalizedDecimalField(serializers.DecimalField): def to_representation(self, value): if value is None: return '' if not isinstance(value, decimal.Decimal): value = decimal.Decimal(str(value).strip()) quantized = self.quantize(value) quantized = quantized.normalize() if self.localize: return localize_input(quantized) return '{:f}'.format(quantized) class CustomModelSerializer(serializers.ModelSerializer): serializer_field_mapping = ( serializers.ModelSerializer.serializer_field_mapping.copy() ) serializer_field_mapping[models.DecimalField] = NormalizedDecimalField
あとはシリアライザの基底クラスを CustomModelSerializer
に変更するだけで、各DecimalFieldから末尾のゼロを除外できます。
- class MySerializer(serializers.ModelSerializer): + class MySerializer(CustomModelSerializer):
モデルのプロパティがDecimal値を返す場合には、シリアライザクラスに NormalizedDecimalField
を明示的に定義してください。
class MySerializer(CustomModelSerializer): my_property = NormalizedDecimalField(max_digits=..., decimal_places=...)