Serializing Django simple history items the same way as the main model

Viewed 194

I am trying to work with Django rest framework in conjunction with Django simple history. This answer has gotten me pretty far with understanding how to serialize the history items of a model. This works well for simple cases, but my model has a calculated field ("store" in the example below). The problem is that the the serialization of the history field doesn't seem to capture these. How to I serialize the history in the same way as the main model? Is it possible to do this in the to_representation method of the HistoricalRecordField?

class MyModel(models.Model):
    ...
    history = HistoricalRecords()

    @property
    def store(self):
          return {}



class HistoricalRecordField(serializers.ListField):
    child = serializers.DictField()

    def to_representation(self, data):
        return super().to_representation(data.values())



class MySerializer(serializers.ModelSerializer):
    ...
    store = serializers.DictField(child=serializers.CharField(), read_only=True)
    history = HistoricalRecordField(read_only=True)
  
    class Meta:
        model = MyModel

What I get is something like:

[
    {
        "id": 1,
        "store": {} 
        "history": [
            {
                "history_id": 1,
                "id": 1,
                "history_date": "2016-11-22T08:02:08.739134Z",
                "history_type": "+",
                "history_user": 1
            },
            {
                "history_id": 2,
                "id": 1,
                "history_date": "2016-11-22T08:03:50.845634Z",
                "history_type": "~",
                "history_user": 1
            }
        ]
    }
]

But what I want are the history items without the history columns and with the "store" field which doesn't show up. Basically I'd like the list of history items to be serialized like they were items from the main model:

[
    {
        "id": 1,
        "store": {...} ,
        ...
        "history": [
            {
                "store": {...},
                ...
                "id": 1,
            },
            {
                "store": {...},
                ...
                "id": 1,
            }
        ]
    }
]
1 Answers

The solution that I found was to create a separate serializer for the historical records that acted the same way as the main serializer. Then use that serializer in the to_representation method of HistoricalRecordfield. Note that you can't use the main serializer (MySerializer) as it creates recursion.

class HistoricalSerializer(serializers.ModelSerializer):
    ...
    store = serializers.DictField(child=serializers.CharField(), read_only=True)

    class Meta:
        model = MyModel

class HistoricalRecordField(serializers.ListField):
    child = serializers.DictField()

    def to_representation(self, data):
        dvs = HistoricalRecordSerializer(data, many=True).data
        return super().to_representation(dvs)
Related