【问题标题】:ModelSerializer field validation for empty string空字符串的 ModelSerializer 字段验证
【发布时间】:2016-09-04 14:16:02
【问题描述】:

我在使用 django rest 框架时遇到问题。
我的前面是向 drf 发布数据,其中一个字段可以是null 或空字符串""

# models.py
class Book(models.Model):
    title = models.CharField(max_length=100)
    publication_time = models.TimeField(null=True, blank=True)


# serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('id', 'title', 'publication_time')

publication_time 可以是 blank""

空白案例有效,事实上,当我发布一个 json {"title": "yeah a book", "publication_time": none} 时,一切都很好。

当我发送{"title": "yeah a book", "publication_time":""} 时,我确实收到了验证错误"Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]]."

我尝试向序列化程序类添加字段验证器:

def validate_publication_time(self, value):
    if not value:
        return None

甚至使用 extra_kwargs

# ....
def empty_string_to_none(value):
    if not value:
        return None    

# ....
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ('id', 'title', 'publication_time')
        extra_kwargs = {'publication_time': {'validators' : [empty_string_to_none]} }

我想要做的是在任何验证发生之前或作为第一个验证规则之前将一个空字符串转换为 None (序列化程序和模型应该接受)。

问题:
问题是 validate_publication_time 从未被调用过,我什至在点击该函数之前就收到了验证错误。正如我understood 一样,验证器的运行有一个特定的顺序,但现在我不知道如何解决我的问题。

问题:
我想要做的是实际清理数据,以便在运行任何验证之前将"" 转换为None。可能吗?怎么样?

编辑: 这是我的序列化程序的表示:

# from myapp.serializers import BookSerializer
# serializer = BookSerializer()
# print repr(serializer)
# This is the print result:
BookSerializer():
    id = IntegerField(label='ID', read_only=True)
    title = CharField(max_length=100)
    publication_time = TimeField(allow_null=True, required=False)

如您所见,publication_time 字段可能为空,不是吗?

【问题讨论】:

  • 你有没有找到这个问题的好答案?

标签: json django validation serialization django-rest-framework


【解决方案1】:

我遇到了同样的问题,终于找到了解决办法。

为了在错误发生之前处理'',需要重写to_internal_value方法:

class BookSerializer(serializers.ModelSerializer)::
    def to_internal_value(self, data):
        if data.get('publication_time', None) == '':
            data.pop('publication_time')
        return super(BookSerializer, self).to_internal_value(data)

【讨论】:

  • 很好的答案,谢谢!我只会制作以下版本:将 if 语句转换为 if 'publication_time' in data and data['publication_time'] == '' 并设置 data['publication_time'] = None 如果它通过。由于作者想将空字符串转换为None,所以我认为这样会更精确。
【解决方案2】:

kwargallow_nullallow_blank 不是 nullblank

【讨论】:

  • 我不这么认为,那些是 django 模型字段,而不是序列化器字段
  • 我已经编辑了这个问题,所以你也可以看到序列化程序实例表示
  • 我认为这应该是正确的答案。这对我有用。
  • @Leonardo 他的意思是,当您在序列化程序的元数据中声明变量时,您可以说 sometext= serializers.CharField(allow_blank=True) 不在模型中,py 而是在序列化程序 py 中。这也会覆盖默认行为。 django-rest-framework.org/api-guide/fields
【解决方案3】:

您可以覆盖序列化程序的 save 方法,在该方法中检查该值是否为空字符串,然后将其设置为 Null。

在您的序列化程序中(未经测试):

def save(self, *args, **kwargs)
    if self.publication_time == "":
        self.publication_time = Null
    super.save(*args, **kwargs)

或者,您可以在视图中这样做(我就是这样做的):

def perform_update(self, serializer):
    publication_time = self.kwargs['publication_time']
    if publication_time == "":
        publication_time = Null
    serializer.save(publication_time=publication_time)

只有这样,如果您在 POST 时也需要它,您还需要覆盖 perform_create,而不仅仅是在 PUT 时

【讨论】:

    【解决方案4】:

    你试过override serialization behavior吗?你需要的是覆盖.to_internal_value(self, data)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-13
      • 2019-11-03
      • 1970-01-01
      • 2019-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-21
      相关资源
      最近更新 更多