Skip to content

Instantly share code, notes, and snippets.

@stephenmcd
Created February 19, 2014 10:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save stephenmcd/9089444 to your computer and use it in GitHub Desktop.
Save stephenmcd/9089444 to your computer and use it in GitHub Desktop.
from rest_framework import serializers
class HyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
"""
This is a performance wrapper for HyperlinkedIdentityField.
We save a ton of time by not calling reverse potentially
thousands of times per request.
"""
def __init__(self, *args, **kwargs):
self.view_url = kwargs.pop("view_url", "")
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
def field_to_native(self, obj, field_name):
return "http%s://%s%s" % (
"s" if not settings.DEBUG else "",
self.context["request"]._request.META["HTTP_HOST"],
self.view_url % obj.id,
)
# Example :
# items = HyperlinkedIdentityField(view_url="/api/subscriptions/%s/items/",
# view_name="subscription_item_list", pk_url_kwarg="subscription_id")
@stephenmcd
Copy link
Author

Here's an improved version that pre-computes the urlpattern the first time the field is used - this gives similar performance without hard-coding the urlpattern.

import sys
ID_TOKEN = str(sys.maxint)
URLS = {}

class HyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
    """
    This is a performance wrapper for HyperlinkedIdentityField.
    We save a ton of time by pre-computing the URL the first time it's
    accessed, to save calling reverse potentially thousands of times
    per request.
    """

    def field_to_native(self, obj, field_name):
        try:
            url = URLS[self.view_name]
        except KeyError:
            real_id = obj.id
            obj.id = ID_TOKEN
            url = URLS[self.view_name] = super(HyperlinkedIdentityField,
                self).field_to_native(obj, field_name)
            obj.id = real_id
        return url.replace(ID_TOKEN, str(obj.id))

@GeekGawd
Copy link

I know its been a long time @stephenmcd but the improved version of the code won't work as Django is stateless and the urls dict will just reset after each request, sir. You would have to use cache to set the url.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment