Using drf-nested-routers with nested HyperlinkedIdentityFields

1.5k Views Asked by At

I am trying to generate nested HATEOAS links in a serializer using the drf-nested-routes package. My current setup would be as follows:

/resource_a/<pk>
/resource_a/<pk>/resource_b/<pk>
/resource_a/<pk>/resource_b/<pk>
/resource_a/<pk>/resource_b/<pk>/resource_c

I am unable to create a HyperlinkedIdentityField that points to the last route. According to the documentation, one can create hyperlinked fields like this:

nameservers = HyperlinkedIdentityField(
    view_name='domain-nameservers-list',
    lookup_url_kwarg='domain_pk'
)

Or

nameservers = NestedHyperlinkedRelatedField(
    many=True,
    read_only=True,   # Or add a queryset
    view_name='domain-nameservers-detail'
    parent_lookup_url_kwargs={'domain_pk': 'domain__pk'}
)

But these approaches fail when trying to reach a resource that is 2 layers deep in the URL hierarchy. The first method is not compatible, as it does not allow to add a second lookup_url_kwarg, and as for the second one, it throws an exception (ImproperlyConfigured) when configuring with the (in my opinion) proper attributes (resource_a__pk, resource_b__pk).

Is this at all possible with this package? Otherwise I will resort to a simpler solution using a SerializerMethodField:

resource_c = serializers.SerializerMethodField()

def get_resource_c(self, obj):
        url = reverse('resource_b-resource_c-list', kwargs=dict(resource_a_pk=obj.resource_a.pk, resource_b_pk=obj.pk))
        return self.context['request'].build_absolute_uri(url)

Thanks in advance!

1

There are 1 best solutions below

0
On BEST ANSWER

I've done this before using NestedHyperlinkedRelatedField and it definitely works. My guess is that your configuration is not correct. One thing I noticed is that you use parent_lookup_url_kwargs while in my case I use parent_lookup_kwargs.

Based on your explanation I think it needs to look like this

NestedHyperlinkedRelatedField(..., 
    parent_lookup_kwargs={
          'resource_a_pk': '<how to reach resource_a pk from resource_b>'})