Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
411 views
in Technique[技术] by (71.8m points)

Adding root element to json response (django-rest-framework)

I am trying to determine the best way to add a root element to all json responses using django and django-rest-framework.

I think adding a custom renderer is the best way to accomplish what I want to achieve and this is what I have come up with so far:

from rest_framework.renderers import JSONRenderer

class CustomJSONRenderer(JSONRenderer):
#override the render method
def render(self, data, accepted_media_type=None, renderer_context=None):
    #call super, as we really just want to mess with the data returned
    json_str = super(CustomJSONRenderer, self).render(data, accepted_media_type, renderer_context)
    root_element = 'contact'

    #wrap the json string in the desired root element
    ret = '{%s: %s}' % (root_element, json_str) 

    return ret

The tricky part now is dynamically setting the root_element based on the view that render() is being called from.

Any pointers/advice would be greatly appreciated,

Cheers

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For posterity, below is the final solution. It has grown slightly from the original as it now reformats paginated results as well.

Also I should have specified before, that the reason for the JSON root element is for integration with an Ember front end solution.

serializer:

from rest_framework.serializers import ModelSerializer
from api.models import Contact

class ContactSerializer(ModelSerializer):
    class Meta:
        model = Contact
        #define the resource we wish to use for the root element of the response
        resource_name = 'contact' 
        fields = ('id', 'first_name', 'last_name', 'phone_number', 'company')

renderer:

from rest_framework.renderers import JSONRenderer

class CustomJSONRenderer(JSONRenderer):
    """
        Override the render method of the django rest framework JSONRenderer to allow the following:
        * adding a resource_name root element to all GET requests formatted with JSON
        * reformatting paginated results to the following structure {meta: {}, resource_name: [{},{}]}

        NB: This solution requires a custom pagination serializer and an attribute of 'resource_name'
        defined in the serializer
    """
    def render(self, data, accepted_media_type=None, renderer_context=None):
        response_data = {}

        #determine the resource name for this request - default to objects if not defined
        resource = getattr(renderer_context.get('view').get_serializer().Meta, 'resource_name', 'objects')

        #check if the results have been paginated
        if data.get('paginated_results'):
            #add the resource key and copy the results
            response_data['meta'] = data.get('meta')
            response_data[resource] = data.get('paginated_results')
        else:
            response_data[resource] = data

        #call super to render the response
        response = super(CustomJSONRenderer, self).render(response_data, accepted_media_type, renderer_context)

        return response

pagination:

from rest_framework import pagination, serializers

class CustomMetaSerializer(serializers.Serializer):
    next_page = pagination.NextPageField(source='*')
    prev_page = pagination.PreviousPageField(source='*')
    record_count = serializers.Field(source='paginator.count')

class CustomPaginationSerializer(pagination.BasePaginationSerializer):
    # Takes the page object as the source
    meta = CustomMetaSerializer(source='*')
    results_field = 'paginated_results'

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...