Project

Profile

Help

Issue #2414

Updated by amacdona@redhat.com over 7 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