空字符串的ModelSerializer字段验证

时间:2016-05-09 19:53:28

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

我遇到了django休息框架的问题 我的前面是将数据发布到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字段可以为null,不是吗?

5 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,最后找到了解决方案。

为了在错误发生之前处理'',您需要覆盖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)

答案 1 :(得分:2)

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

答案 2 :(得分:1)

您可以覆盖序列化程序的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)

只有这样你才需要覆盖perform_create,如果你在POST时也需要这样做,不仅仅是当PUT

答案 3 :(得分:0)

publication_timeTimeField,因此您不能指望将空字符串""保存到其中。你得到错误是因为你只是想这样做。

当您通过"publication_time": none时,一切正常,因为none在那里被视为NULL值,并且由于您设置了null=True,因此不会抛出任何验证错误。

您对验证运行的顺序也是正确的。如果您创建了方法validate_publication_time,则在这种情况下它永远不会运行,因为空字符串与TimeField指定的格式不匹配,并且仅在该验证中引发错误。

答案 4 :(得分:0)

kwargallow_nullallow_blank不是nullblank