django 空字符串的ModelSerializer字段验证

bihw5rsg  于 2023-01-21  发布在  Go
关注(0)|答案(5)|浏览(176)

我在使用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

或者甚至使用额外的_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

**EDIT:**这是我的序列化程序的表示形式:

# 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字段可能为空,不是吗?

mnowg1ta

mnowg1ta1#

我也遇到了同样的问题,终于找到了解决办法。
为了在错误发生之前处理'',需要重写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)
4si2a6ki

4si2a6ki2#

是否尝试过重写序列化行为?您需要的是重写.to_internal_value(self, data)

62lalag4

62lalag43#

那么kwargallow_nullallow_blank,而不是nullblank

fhg3lkii

fhg3lkii4#

您可以重写序列化程序的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时,那么您还需要覆盖perform_create

x8goxv8g

x8goxv8g5#

@Ivan Blinov的答案是正确的,但您应该允许数据可变,否则您会得到此错误:

AttributeError: This QueryDict instance is immutable

所以完整的答案是:

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

相关问题