serializers for use at the model field level

33 views
Skip to first unread message

Nate Dudenhoeffer

unread,
Sep 26, 2016, 9:20:14 AM9/26/16
to Django REST framework
DRF serializers are great! The make validating data and converting json data to python types super flexible and reliable. I would like to start using them at the model level, not only at the view (api endpoint) level.

The use case is that I have lots of models which contain  a JSONField, and contain data which may be referenced by parts of the sytem not directly related to an api endpoint. I would like to use a DRF serializer to get the right python types and defaults when that date comes out of the database. Has anyone implemented something similar? Are there pit-falls to this approach I should be aware of (an exception for invalid data it the database is fine)? Do you have a suggestion of a better way to accomplish this?

The following simplified psuedo-code seems to do what I am looking for (get_db_prep_value should be implemented too).


class JSONField(models.JSONField):

    def __init__(self, serializer_class=None, *args, **kwargs):
    """
:param serializer_class: a rest framework serializer which will be used to deserialize the json data from the database.
Among other things this may create datetime objects for some fields. Be aware that fields not present on the serializer
may be lost, and if there is invalid data in the database it will raise
"""
self.serializer_class = serializer_class
models.TextField.__init__(self, *args, **kwargs)

def to_python(self, value):
"""
Overrides the django-extensions default to use a Decimal instead of a float
:param value:
:return:
"""
    data = json.loads(value)
if self.serializer_class is not None:
#       Use string names for serializers because they will often reference models and this avoid circular imports
module_name, class_name = self.serializer_class.rsplit('.', 1)
serializer_class = getattr(import_module(module_name), class_name)
serializer = serializer_class(data=data)
serializer.is_valid()
data = serializer.validated_data
return data
Reply all
Reply to author
Forward
0 new messages