Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to skip validation for DRF serializer FloatField

Problem

I need to add the ability to save the minimum_commission as positive number, but None is also available. I have added the serialiser:

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',
        )

But when I pass the empty string from the form(or shell), I see the A valid number is required validation error.

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')])])

Possible solution

At first I have added custom field: BlankableFloatField which convert empty string to the None:

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)

and added the custom validation:

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

For now it works as expected:

In [38]: ser = RentalTestSerializer(data={'minimum_commission': ''})

In [39]: ser.is_valid()
Out[39]: True

but I think is there way to do it more elegant?


UPD:

as I see the main issue is into passing the empty string from the form. I need it to reset the minimum_commission column. So, the final solution is:

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:

After plaing with the solution of processing empty string I found that clearer is to skip sending empty string on front-end at all and set the default=None into serialiser. Also, the custom field is not needed anymore.

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',
        )
like image 315
Ivan Rostovsky Avatar asked Dec 19 '25 22:12

Ivan Rostovsky


1 Answers

Like I mentioned in the comment - the appartement model would be useful.

But if I understand correctly, what you want to achieve should be quite simple as follows:

class Appartement(models.Model):
    minimum_commission = models.FloatField(blank=True, null=True, default=None)

class RentalTestSerializer(serializers.ModelSerializer):

    class Meta:
        model = Appartement
        fields = (
            'minimum_commission',
        )

With this implementation, minimum_commission is optional, and it accepts null values too.

like image 63
Enthusiast Martin Avatar answered Dec 21 '25 12:12

Enthusiast Martin