Django: changing contents on a field on every save-like action

Before committing a record to the database, I want to do a sanity check on a certain field. More precisely, it is an ArrayField and I want to remove any NaN/None values and replace them by zero.

However, there are many ways to create said record. A user might MyObject().save(), or MyObject.objects.create(), or MyObject.objects.bulk_create(), and even MyObject.objects.bulk_update(field=my_field). I believe there are also ways in that Django Rest Framework might use.

How can I be sure that NaN/None is always replaced by zero before committing to the database? Should I overwrite all the above methods? Should I create a custom field that inherits from ArrayField but does all the data munging? What is the best practice?

I ended up taking my own advice and subclassed DecimalField into something that can turn NaNs into None:

NOTE python<3.10 type-hinting syntax

import math
from typing import Any, Union

from django.db.models.fields import DecimalField


class NanToNoneDecimalField(DecimalField):
    """Converts a NaN value to None because NaN is no longer
    supported for DecimalField in in Django 4.2
    """

    def to_python(self, value: Union[Any, None]) -> Union[Any, None]:
        try:
            if math.isnan(value):
                return None
        except TypeError:
            pass

        return super().to_python(value)
Back to Top