DjangoRestFramework ChoiceField无法通过浮点值验证

时间:2019-02-05 11:50:38

标签: django python-3.x django-rest-framework choicefield django-model-utils

我对serializers.ChoiceField的验证逻辑有疑问。正如我在代码中看到的,这里是to_internal_value()中的ChoiceField,用于验证客户端输入:

def to_internal_value(self, data):
    if data == '' and self.allow_blank:
        return ''

    try:
        return self.choice_strings_to_values[six.text_type(data)]
    except KeyError:
        self.fail('invalid_choice', input=data)

这是我对Django模型的声明:

class MyModel(BaseModel, ScopedModelMixin):
    my_field = models.FloatField(choices=MY_FLOAT_CHOICES, default=MY_FLOAT_CHOICES.default_value)

这是我来自django-model-utils==2.6.1的选择声明对象:

from model_utils import Choices

MY_FLOAT_CHOICES = Choices(
    (1.0, 'choice1', 'Choice1'),
    (1.5, 'default_value', 'Choice2'),
    (2.0, 'choice3', 'Choice3')
)

因此,模型序列化器中生成的字段是serializers.ChoiceField,具有在先前声明的模型级别提供的选项。

在验证来自客户端的用户输入时,DRF无法正确验证浮点值。例如,当我发送:

{
    "myField": 1
}

它抛出"\"1\" is not a valid choice."。因此,当我将调试器带到这行时

从先前显示的return self.choice_strings_to_values[six.text_type(data)]的{​​{1}}中

to_internal(),我看到它实际上是在选择列表中试图找到ChoiceField。当我使用以下选项更新选择时:

'1'

它不会失败,但是然后我又遇到了同样的问题,那就是从MY_FLOAT_CHOICES = Choices( (1, 'choice1', 'Choice1'), (1.5, 'default_value', 'Choice2'), (2, 'choice3', 'Choice3') ) 发送1.0而不是发送它,并且循环不断。我应该在DRF信息库上提出问题,还是有更好的选择?

1 个答案:

答案 0 :(得分:0)

我想您必须将int键转换为float,以便它可以在选择元组中找到它。

def to_internal_value(self, data):
    if data == '' and self.allow_blank:
        return ''

    try:
        key = six.text_type(float(data))
        return self.choice_strings_to_values[key]
    except (ValueError, KeyError) as e:
        self.fail('invalid_choice', input=data)