Django Rest Framework 忽略自定义字段

Django Rest Framework ignoring custom field

我有一个带有可为空布尔字段的模型,我希望以一种将输出中的 null 转换为 false.

的方式进行序列化

我的模特:

class UserPreferences(models.Model):
    receive_push_notifications = models.BooleanField(
        null=True, blank=True,
        help_text=("Receive push notifications))

我正在尝试使用这样的自定义字段:

class StrictlyBooleanField(serializers.Field):
    def to_representation(self, value):
        # Force None to False
        return bool(value)

    def to_internal_value(self, data):
        return bool(data)


class UserPreferencesSerializer(serializers.ModelSerializer):
    class Meta(object):
        model = UserPreferences
        fields = ('receive_push_notifications',)

    receive_push_notifications = StrictlyBooleanField()

但这不起作用,我仍然在 API 回复中看到 null

我想我一定是在连接它时遗漏了一些简单的东西,因为如果我将我的 to_representation 替换为:

,我什至不会收到错误消息
def to_representation(self, value):
    raise

DRF 似乎根本没有调用我的方法...我在这里缺少什么?

说明

查看rest framework的Serializerto_representation方法后,您会发现它遍历了所有字段并为每个字段调用了field.get_attribute方法。如果从该方法中编辑的值 return 是 None,它会完全跳过调用 field.to_representation 并将 None 设置为字段值。

# Serializer's to_representation method
def to_representation(self, instance):
    """
    Object instance -> Dict of primitive datatypes.
    """
    ret = OrderedDict()
    fields = self._readable_fields

    for field in fields:
        try:
            attribute = field.get_attribute(instance)
        except SkipField:
            continue

        # We skip `to_representation` for `None` values so that fields do
        # not have to explicitly deal with that case.
        #
        # For related fields with `use_pk_only_optimization` we need to
        # resolve the pk value.
        check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
        if check_for_none is None:
            ret[field.field_name] = None
        else:
            ret[field.field_name] = field.to_representation(attribute)

    return ret

解决方案

如果值为 None

,则通过调用 super().get_attribute 和 return False 覆盖 field.get_attribute
class StrictlyBooleanField(serializers.Field):
    def get_attribute(self, instance):
        attribute = super().get_attribute(instance)
        return bool(attribute)

    def to_representation(self, value):
        return value

    def to_internal_value(self, data):
        return bool(data)

您可以在序列化程序中编写一个简单的函数

 class UserPreferencesSerializer(serializers.ModelSerializer):
     yourField = serializers.SerializerMethodField(read_only=True)
     class Meta(object):
         model = UserPreferences
         fields = ['receive_push_notifications', 'yourField']

         def get_yourField(self, obj):
              if obj.receive_push_notifications == null:
                   return False
              else:
                   return True