[Solved]-Django-rest-framework HyperlinkedIdentityField with multiple lookup args

13👍

I’m not sure if you’ve solved this problem yet, but this may be useful for anyone else who has this issue. There isn’t much you can do apart from overriding HyperlinkedIdentityField and creating a custom serializer field yourself. An example of this issue is in the github link below (along with some source code to get around it):

https://github.com/tomchristie/django-rest-framework/issues/1024

The code that is specified there is this:

from rest_framework.relations import HyperlinkedIdentityField
from rest_framework.reverse import reverse

class ParameterisedHyperlinkedIdentityField(HyperlinkedIdentityField):
    """
    Represents the instance, or a property on the instance, using hyperlinking.

    lookup_fields is a tuple of tuples of the form:
        ('model_field', 'url_parameter')
    """
    lookup_fields = (('pk', 'pk'),)

    def __init__(self, *args, **kwargs):
        self.lookup_fields = kwargs.pop('lookup_fields', self.lookup_fields)
        super(ParameterisedHyperlinkedIdentityField, self).__init__(*args, **kwargs)

    def get_url(self, obj, view_name, request, format):
        """
        Given an object, return the URL that hyperlinks to the object.

        May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
        attributes are not configured to correctly match the URL conf.
        """
        kwargs = {}
        for model_field, url_param in self.lookup_fields:
            attr = obj
            for field in model_field.split('.'):
                attr = getattr(attr,field)
            kwargs[url_param] = attr

        return reverse(view_name, kwargs=kwargs, request=request, format=format)

This should work, in your case you would call it like this:

url = ParameterisedHyperlinkedIdentityField(view_name="user-device-detail", lookup_fields=(('<model_field_1>', 'user_pk'), ('<model_field_2>', 'uid')), read_only=True)

Where <model_field_1> and <model_field_2> are the model fields, probably ‘id’ and ‘uid’ in your case.

Note the above issue was reported 2 years ago, I have no idea if they’ve included something like that in newer versions of DRF (I haven’t found any) but the above code works for me.

Leave a comment