Project

Profile

Help

Issue #2414

Updated by amacdona@redhat.com about 3 years ago

`HyperlinkedRelatedField` for detail list views are passed incorrect `view_names`.

As an example, this should be the most simple working detail importer serializer possible:

<pre><code class="python">
class TestImporterSerializer(ImporterSerializer):
# _href is provided by the base class, which is a subclass of `MasterModelSerializer`

class Meta:
model = TestImporter
fields = ImporterSerializer.Meta.fields
</code></pre>

This creates the following error from Django (viewed from the browsable web API):
<pre>
ImproperlyConfigured at /api/v3/importers/test/

Could not resolve URL for hyperlinked relationship using view name "testimporter-detail". "importers-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

Request Method: GET
Request URL: http://192.168.121.160:8000/api/v3/importers/test/
Django Version: 1.8.16
Exception Type: ImproperlyConfigured
Exception Value:

Could not resolve URL for hyperlinked relationship using view name "testimporter-detail". "importers-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

Exception Location: /usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/relations.py in to_representation, line 386
Python Executable: /home/vagrant/.virtualenvs/pulp/bin/python
Python Version: 3.5.2
Python Path:

['/home/vagrant/devel/pulp/app/pulp/app',
'/home/vagrant/.virtualenvs/pulp/lib64/python35.zip',
'/home/vagrant/.virtualenvs/pulp/lib64/python3.5',
'/home/vagrant/.virtualenvs/pulp/lib64/python3.5/plat-linux',
'/home/vagrant/.virtualenvs/pulp/lib64/python3.5/lib-dynload',
'/usr/lib64/python3.5',
'/usr/lib/python3.5',
'/home/vagrant/.virtualenvs/pulp/lib/python3.5/site-packages',
'/home/vagrant/devel/devel/pulp-dev',
'/home/vagrant/devel/pulp/app',
'/usr/lib/python3.5/site-packages/psycopg2-2.6.2-py3.5-linux-x86_64.egg',
'/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg',
'/usr/lib/python3.5/site-packages/django_filter-0.15.3-py3.5.egg',
'/usr/lib/python3.5/site-packages/django_extensions-1.7.4-py3.5.egg',
'/usr/lib/python3.5/site-packages/django_crispy_forms-1.6.1-py3.5.egg',
'/usr/lib/python3.5/site-packages/Django-1.8.16-py3.5.egg',
'/usr/lib/python3.5/site-packages/coreapi-2.0.9-py3.5.egg',
'/usr/lib/python3.5/site-packages/celery-4.0.0-py3.5.egg',
'/usr/lib/python3.5/site-packages/uritemplate-3.0.0-py3.5.egg',
'/usr/lib/python3.5/site-packages/itypes-1.1.0-py3.5.egg',
'/usr/lib/python3.5/site-packages/kombu-4.0.0-py3.5.egg',
'/usr/lib/python3.5/site-packages/billiard-3.5.0.2-py3.5.egg',
'/usr/lib/python3.5/site-packages/pytz-2016.7-py3.5.egg',
'/usr/lib/python3.5/site-packages/amqp-2.1.1-py3.5.egg',
'/usr/lib/python3.5/site-packages/vine-1.1.3-py3.5.egg',
'/home/vagrant/devel/pulp/plugin',
'/home/vagrant/devel/pulp/exceptions',
'/home/vagrant/devel/pulp/client_lib',
'/home/vagrant/devel/pulp/common',
'/home/vagrant/devel/pulp/client_consumer',
'/home/vagrant/devel/pulp/devel',
'/home/vagrant/devel/pulp/server',
'/home/vagrant/devel/pulp/bindings',
'/home/vagrant/devel/pulp/client_admin',
'/home/vagrant/devel/pulp/streamer',
'/usr/lib/python3.5/site-packages/Twisted-16.5.0-py3.5-linux-x86_64.egg',
'/home/vagrant/devel/pulp/repoauth',
'/home/vagrant/devel/pulp/oid_validation',
'/home/vagrant/devel/pulp/tasking',
'/usr/lib64/python3.5/site-packages',
'/usr/lib/python3.5/site-packages',
'/usr/lib/python3.5/site-packages',
'/home/vagrant/devel/pulp']

Server time: Thu, 10 Nov 2016 19:16:43 18:59:28 +0000
</pre>

This is the traceback from the server:
<pre>
Traceback (most recent call last):
File "/usr/lib/python3.5/site-packages/Django-1.8.16-py3.5.egg/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.5/site-packages/Django-1.8.16-py3.5.egg/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/viewsets.py", line 83, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/views.py", line 477, in dispatch
response = self.handle_exception(exc)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/views.py", line 437, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/views.py", line 474, in dispatch
response = handler(request, *args, **kwargs)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/mixins.py", line 45, in list
return self.get_paginated_response(serializer.data)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/serializers.py", line 725, in data
ret = super(ListSerializer, self).data
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/serializers.py", line 643, in to_representation
self.child.to_representation(item) for item in iterable
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/serializers.py", line 643, in <listcomp>
self.child.to_representation(item) for item in iterable
File "/home/vagrant/devel/pulp/app/pulp/app/serializers/base.py", line 187, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/usr/lib/python3.5/site-packages/djangorestframework-3.5.3-py3.5.egg/rest_framework/relations.py", line 386, in to_representation
raise ImproperlyConfigured(msg % self.view_name)
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "importers-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

</pre>

The problem is that the view_name being passed to the HyperlinedRelatedField is `testimporter-detail`, which does not exist. What should be created is `<master_names>-<detail_name>-detail`, which in this example would be importers-test-detail.

There is a workaround, the plugin writer just needs to override `_href` with the correct view_name, but this isn't ideal and should be handled by the base class.

<pre><code class="python">
class TestImporterSerializer(ImporterSerializer):
_href = serializers.HyperlinkedIdentityField(view_name='importers-test-detail')

class Meta:
model = TestImporter
fields = ImporterSerializer.Meta.fields

</code></pre>

Back