【发布时间】:2019-10-16 15:23:35
【问题描述】:
问题
我需要添加将minimum_commission 保存为正数的功能,但 None 也可用。我已经添加了序列化器:
class Appartement(models.Model):
minimum_commission = models.FloatField(null=True, default=None)
class RentalTestSerializer(serializers.ModelSerializer):
minimum_commission = serializers.FloatField(required=False, min_value=0)
class Meta:
model = Appartement
fields = (
'minimum_commission',
)
但是当我从表单(或外壳)传递空字符串时,我看到A valid number is required 验证错误。
In [21]: ser = RentalTestSerializer(data={'minimum_commission': ''})
In [22]: ser.is_valid()
Out[22]: False
In [23]: ser.errors
Out[23]:
ReturnDict([('minimum_commission',
[ErrorDetail(string=u'A valid number is required.', code=u'invalid')])])
可能的解决方案
起初我添加了自定义字段:BlankableFloatField,它将空字符串转换为无:
class BlankableFloatField(serializers.FloatField):
"""
We wanted to be able to receive an empty string ('') or 'null' for a float field
and in that case turn it into a None number
"""
def to_internal_value(self, data):
if data in ['', 'null']:
return None
return super(BlankableFloatField, self).to_internal_value(data)
并添加了自定义验证:
class RentalTestSerializer(serializers.ModelSerializer):
minimum_commission = BlankableFloatField(required=False)
class Meta:
model = Appartement
fields = (
'minimum_commission',
)
def validate_minimum_commission(self, value):
if value and value < 0:
raise serializers.ValidationError(_("Minimum commission should be greater than 0"))
return value
现在它按预期工作:
In [38]: ser = RentalTestSerializer(data={'minimum_commission': ''})
In [39]: ser.is_valid()
Out[39]: True
但我认为有没有办法让它更优雅?
更新:
正如我所见,主要问题是从表单中传递空字符串。我需要它来重置minimum_commission 列。所以,最终的解决方案是:
class Appartement(models.Model):
# I have added the blank=True and validator
minimum_commission = models.FloatField(null=True, default=None, blank=True, validators=[MinValueValidator(0.0)])
class RentalTestSerializer(serializers.ModelSerializer):
# I continue to use the custom field to transform empty space to the None
# but instead of custom validation just added the allow_null=True and min_value validator.
minimum_commission = BlankableFloatField(required=False, allow_null=True, min_value=0)
class Meta:
model = Appartement
fields = (
'minimum_commission',
)
UPD2:
在了解了处理空字符串的解决方案后,我发现更清楚的是完全跳过在前端发送空字符串并将default=None设置为序列化器。此外,不再需要自定义字段。
class Appartement(models.Model):
minimum_commission = models.FloatField(null=True, default=None)
class RentalTestSerializer(serializers.ModelSerializer):
minimum_commission = serializer.FloatField(required=False, allow_null=True, min_value=0, default=None)
class Meta:
model = Appartement
fields = (
'minimum_commission',
)
【问题讨论】:
-
可以附上公寓的型号吗?重要的是查看您是否可以为该字段存储 null
-
在模型中定义为
minimum_commission = models.FloatField(null=True, default=None)
标签: python django django-rest-framework