Django-rest-framework HyperlinkedIdentityField with multiple search arguments

I have the following url in my urls:

url(r'^user/(?P<user_pk>[0-9]+)/device/(?P<uid>[0-9a-fA-F\-]+)$', views.UserDeviceDetailView.as_view(), name='user-device-detail'), 

Note that it has two fields: user_pk and uid . The URL will look something like this: https://example.com/user/410/device/c7bda191-f485-4531-a2a7-37e18c2a252c .

In the detailed view for this model, I am trying to populate a url field that will contain a link to the model.

In the serializer, I have:

 url = serializers.HyperlinkedIdentityField(view_name="user-device-detail", lookup_field='uid', read_only=True) 

however, I don’t think because the URL has two fields:

django.core.exceptions.ImproperlyConfigured: Failed to resolve URLs for hyperlinks using view name "user-device-detail". You may not have been able to include the linked model in your API, or you might have incorrectly configured the lookup_field attribute in this field.

How do you use a HyperlinkedIdentityField (or any of the Hyperlink*Field ) when a URL has two or more URL pattern elements? (search fields)?

+7
python django django-rest-framework
source share
1 answer

I am not sure that you have solved this problem yet, but it can be useful for everyone who has this problem. There are not many options besides redefining HyperlinkedIdentityField and creating your own serializer field. An example of this problem is given below in the github link (along with some source code):

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

Specified Code:

 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, possibly "id" and "uid" in your case.

Please note that the above problem was reported 2 years ago, I have no idea if they included something similar in newer versions of DRF (I did not find them), but the code above works for me.

+5
source share

All Articles