【问题标题】:Django REST Framework: how to substitute null with empty string?Django REST Framework:如何用空字符串替换 null?
【发布时间】:2019-02-09 15:46:30
【问题描述】:

我有一个具有以下 ImageField 类型的模型:

class Attendance(models.Model):
    face_image = models.ImageField(, blank=True, null=True, storage=MediaStorage())

基于模型的序列化器

class AttendanceSerializer(serializers.ModelSerializer):

    class Meta:
        model = Attendance
        fields = ('id','face_image')

但是如果 imagefield 为 null,则显示如下

Its now showing like this in the json

  {
    "id": 1,
    "face_image": null
  }

如果 face_image (ImageField) 为 None,它将显示输出为 null。我想要的是将 null 替换为像这样的空字符串 ""

【问题讨论】:

    标签: python json django django-rest-framework


    【解决方案1】:

    覆盖AttendanceSerializerto_representation()方法为,

    class AttendanceSerializer(serializers.ModelSerializer):
        class Meta:
            model = Attendance
            fields = ('id', 'face_image')
    
        def to_representation(self, instance):
            data = super().to_representation(instance)
            if not data['face_image']:
                data['face_image'] = ""
            return data

    更新(2019 年 11 月 3 日)

    我有很多字段,我为所有字段重复此代码并不是一个好主意,难道没有更好的方法来为所有字段执行此操作吗?

    class AttendanceSerializer(serializers.ModelSerializer):
        class Meta:
            model = Attendance
            fields = ('id', 'face_image')
    
        def to_representation(self, instance):
            my_fields = {'field_1', 'field_2', 'field_3', 'field_4', 'field_5'}
            data = super().to_representation(instance)
            for field in my_fields:
                try:
                    if not data[field]:
                        data[field] = ""
                except KeyError:
                    pass
            return data

    【讨论】:

    • 我有很多字段,我对所有字段重复此代码并不是一个好主意,难道没有更好的方法来为所有字段执行此操作吗?
    【解决方案2】:

    您可以使用 SerializerMethodField。

    class AttendanceSerializer(serializers.ModelSerializer):
    
        face_image = serializers.SerializerMethodField()
    
        class Meta: 
            model = Attendance
            fields = ('id', 'face_image')
    
        def get_face_image(self, instance):
            return (instance.face_image.url if instance.face_image else '')
    

    【讨论】:

    • 我认为你打破了这个解决方案的创建和更新方法。
    • 你是什么意思? @BearBrown
    • 正如@BearBrown 所说,SerializerMethodField 可能会在写入数据时出现问题
    【解决方案3】:

    序列化程序元中提到的所有字段的迭代代码:

    def to_representation(self, instance):
        data = super().to_representation(instance)
        for key, value in data.items():
            try:
                if not value:
                    data[key] = ""
            except KeyError:
                pass
        return data
    

    【讨论】:

      【解决方案4】:

      为了补充 JPG 的答案,这里有一个 mixin,它允许更轻松地重用覆盖 to_representation 方法的逻辑。它还确保值是 None 而不仅仅是 falsy

      class ConvertNoneToStringSerializerMixin():
          """
          Mixin to convert None to empty strings.
      
          This must be added as the first inherited class. The property `Meta.none_to_str_fields` must
          be defined in order for this to have any effect. This only applies to representations,
          when we export our instance data, not when we acquire and validate data.
          """
          def get_none_to_str_fields(self):
              meta = getattr(self, 'Meta', None)
              return getattr(meta, 'none_to_str_fields', [])
      
          def to_representation(self, instance):
              fields = self.get_none_to_str_fields()
              data = super().to_representation(instance)
      
              if not fields or not isinstance(data, dict):
                  return data
      
              for field in fields:
                  if field in data and data[field] is None:
                      data[field] = ''
              return data
      

      这就是你将如何使用它:

      class AttendanceSerializer(ConvertNoneToStringSerializerMixin, serializers.ModelSerializer):
          class Meta:
              model = Attendance
              fields = ('id', 'face_image')
              none_to_str_fields = ('face_image', )
      
      

      另外,对于那些想知道的人,我们不能覆盖 Field 本身的 to_representation 方法,因为当值为 None 时,Serializer 的核心实现将跳过从字段中调用 to_representation。因此,重写序列化器是实现此目的的唯一方法。

      【讨论】:

        【解决方案5】:

        您可以自定义一个序列化器字段并将其用作 ImageField 的默认 ModelSerializer 字段映射。

        注意:以下代码 sn-p 应在序列化程序类之前加载。

        from rest_framework import serializers
        from django.db import models
        
        
        class MyImageField(serializers.ImageField):
            def __init__(self, *args, **kwargs):
                self.null_as_blank = kwargs.pop('null_as_blank', True)
                if self.null_as_blank:
                    kwargs['allow_blank'] = True
                super().__init__(*args, **kwargs)
        
            def to_internal_value(self, data):
                value = super().to_internal_value(data)
                # Handle deserializer, change blank value back to null.
                if self.null_as_blank and value == '':
                    value = None
                return value
        
            def to_representation(self, value):
                value = super().to_internal_value(value)
                if self.null_as_blank and value is None:
                    value = ''
                return value
        
        
        serializers.ModelSerializer.serializer_field_mapping[models.ImageField] = MyImageField
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-26
          • 2020-06-18
          • 2021-07-12
          • 1970-01-01
          • 2020-06-24
          • 1970-01-01
          • 2011-11-25
          • 2014-03-04
          相关资源
          最近更新 更多