brohemian
brohemian

Reputation: 47

Selectively display Django REST serializer fields

I'm currently working on a project with a requirement I'm having a hard time creating. We have an API built with Django REST, and we want to be able to display only changed data on an endpoint.

Right now we have a feature on the endpoint that only returns the page if a change has been made. To make this work in a GET request, input is UNIX time and it is then converted to a time stamp, which is then compared to a field that represents the last time the model being serialized was modified (via Django's built-in auto_now).

For example:

...api.sample.com/endpoint/?request_time=1418929272.543132 <-- UNIX time stamp

This returns the entire endpoint if there has been any kind of change in any of the model's fields after this timestamp:

 {
    "field1": "data1", 
    "field2": "data2", 
    "field3": "data3", 
    "field4": "data4", 
    "field5": "data5", 
    "field6": "data5",
 }

What I want to be able to do is have this kind of request only return the fields that have changed:

 {
    # Only field 1 and field 5 have changed since the specified time stamp
    "field1": "data1", 
    "field5": "data5", 
 }

I've been working on getting this built for a while and haven't found a satisfactory solution. Even though a complete answer would be nice, I'd be happy if someone could just point me in the right direction here. I've been playing with django-model-utils and a bunch of different mixins and serializer changes, but none of them seem to get the job done.

Upvotes: 1

Views: 1597

Answers (1)

Kevin Brown-Silva
Kevin Brown-Silva

Reputation: 41671

You will have to have something that stores the last modified time for each of these fields, whether it is in the database, the cache, or some other magical place. There is no way for Django to know when a field was last updated, as that is not information that typically needs to be stored.

But I can answer the question in the title

How can I selectively display fields on a serializer?

This is possible in Django REST Framework, and it's actually slightly mentioned in the Dynamically modifying field section of the serializers documentation. You can do it for all fields in a serializer ahead of time by using the mixin that is provided in the documentation. If you need to do it on an object-by-object basis within a serializer, you can also override to_representation on the serializer.

class DemoSerializer(serializers.Serializer):

    def to_representation(self, instance):
        data = super(DemoSerializer, self).to_representation(instance)

        instance_type = data["type"]

        if field_last_modified < last_modified:
            data.pop("field")

        return data

You can use pop to remove the field from the returned data for the specific instance, which will allow you to control what fields are returned.

Upvotes: 4

Related Questions