3

I've developed a web hook to receive transactions from my bank. I use Django-rest-framework to validate the data before saving it to my database. However my bank passes a blank string for the field 'settled' and Django-rest-framework doesn't seem to be able to validate a form with blank values in a datetime field. null is ok, but an empty string is not. What to do?

JSON passed by my bank:

{
    "type": "transaction.created",
    "data": {
        "account_id": "acc_00008gju41AHyfLUzBUk8A",
        "amount": -350,
        "created": "2015-09-04T14:28:40Z",
        "currency": "GBP",
        "description": "Ozone Coffee Roasters",
        "id": "tx_00008zjky19HyFLAzlUk7t",
        "category": "eating_out",
        "is_load": false,
        "settled": "",
        "merchant": {
            "address": {
                "address": "98 Southgate Road",
                "city": "London",
                "country": "GB",
                "latitude": 51.54151,
                "longitude": -0.08482400000002599,
                "postcode": "N1 3JD",
                "region": "Greater London"
            },
            "created": "2015-08-22T12:20:18Z",
            "group_id": "grp_00008zIcpbBOaAr7TTP3sv",
            "id": "merch_00008zIcpbAKe8shBxXUtl",
            "logo": "https://pbs.twimg.com/profile_images/527043602623389696/68_SgUWJ.jpeg",
            "emoji": "",
            "name": "The De Beauvoir Deli Co.",
            "category": "eating_out"
        }
    }
}
class MerchantSerializer(serializers.Serializer):
    id = serializers.CharField(required=True, max_length=50)
    name = serializers.CharField(required=True, max_length=100)
    logo = serializers.URLField(max_length=250, required=False)

class DataSerializer(serializers.Serializer):
    account_id = serializers.CharField(required=True, max_length=50)
    amount = serializers.IntegerField(required=True)
    created = serializers.DateTimeField()
    currency = serializers.CharField(required=True, max_length=3)
    description = serializers.CharField(required=True, max_length=250)
    id = serializers.CharField(required=True, max_length=50)
    category = serializers.CharField(required=True, max_length=100)
    is_load = serializers.BooleanField()
    settled = serializers.DateTimeField(required=False, allow_null=True)
    merchant = MerchantSerializer()

class TransactionSerializer(serializers.Serializer):
    type = serializers.CharField(required=True, max_length=50)
    data = DataSerializer()
rcx935
  • 217
  • 5
  • 15

2 Answers2

2

You need to override to_internal_value:

class DataSerializer(serializers.Serializer):
    def to_internal_value(self, data):
        if data.get('settled') == '':
            data['settled'] = None
        return super().to_internal_value(data)
Jieter
  • 4,101
  • 1
  • 19
  • 31
Lord Elrond
  • 13,430
  • 7
  • 40
  • 80
  • Hi, I tried that but I get: AttributeError: 'super' object has no attribute 'get_internal_value' – rcx935 Jan 17 '20 at 08:00
  • 1
    It'd be great if we didn't have to hack DRF to get it to do perfectly reasonable things that any normal person would expect it to do out of the box. – blimpse Sep 13 '22 at 14:07
0

I think It would be done by trying this settled = serializers.DateTimeField(required=False, allow_null=True , blank = True)

Maede
  • 174
  • 12
  • 1
    I guess your problem can solve by overriding to_internal_value.have you seen https://stackoverflow.com/questions/37124344/modelserializer-field-validation-for-empty-string – Maede Jan 16 '20 at 23:13