django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-detail"
<p>TL;DR: I am getting this error and don't know why:</p>

<blockquote>
  <p>django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-detail". You may have failed to include the related model in your API, or incorrectly configured the 'lookup_field' attribute on this field.</p>
</blockquote>

<p>I am going through the <a href="http://www.django-rest-framework.org/tutorial/3-class-based-views/" rel="nofollow">django-rest-framework tutorial</a> and am currently at a point where function based views (FBV) were switched to class, mixin, and generic based views (CBV, MBV, GBV respectively). After switching to GBV, when I went to test my API, I received this error <code>AssertionError: Expected view SnippetDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the '.lookup_field' attribute on the view correctly.</code>. I did some research and found that <code>lookup_field</code> <a href="http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview" rel="nofollow">needs to be set to the in the urlpatterns</a>. Currently, my urls.py look like this:</p>

<pre><code>from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

# API endpoints
urlpatterns = format_suffix_patterns([
    url(r'^$', views.api_root),
    url(r'^snippets/$',
        views.SnippetList.as_view(),
        name='snippet-list'),
    url(r'^snippets/(?P&lt;id&gt;[0-9]+)/$',
        views.SnippetDetail.as_view(),
        name='snippet-detail'),
    url(r'^users/$',
        views.UserList.as_view(),
        name='user-list'),
    url(r'^users/(?P&lt;id&gt;[0-9]+)/$',
        views.UserDetail.as_view(),
        name='user-detail')
])

# Login and logout views for the browsable API
urlpatterns += [
    url(r'^auth/', include('rest_framework.urls',
                           namespace='rest_framework')),
]
</code></pre>

<p>and my views.py look like so:</p>

<pre><code>from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from snippets.permissions import IsOwnerOrReadOnly

from rest_framework import generics
from rest_framework import permissions
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse

from django.contrib.auth.models import User


@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'users': reverse('user-list', request=request, format=format),
        'snippets': reverse('snippet-list', request=request, format=format)
    })


class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly, )

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly, )
</code></pre>

<p>when I add <code>lookup_field = 'id'</code> in both UserDetail and SnippetDetail, the exception resolves itself. (Yay!). But, when I visit <a href="http://127.0.0.1/users/1/" rel="nofollow">http://127.0.0.1/users/1/</a> <code>ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-detail". You may have failed to include the related model in your API, or incorrectly configured the 'lookup_field' attribute on this field.</code> is thrown. When I check the console, however, there is a second exception: </p>

<blockquote>
  <p>django.urls.exceptions.NoReverseMatch: Reverse for 'user-detail' with
  arguments '()' and keyword arguments '{'pk': 1}' not found. 2
  pattern(s) tried: ['users/(?P[0-9]+)\.(?P[a-z0-9]+)/?$',
  'users/(?P[0-9]+)/$']</p>
  
  <p>During handling of the above exception, another exception occurred:</p>
  
  <p>django.core.exceptions.ImproperlyConfigured: Could not resolve URL for
  hyperlinked relationship using view name "user-detail". You may have
  failed to include the related model in your API, or incorrectly
  configured the 'lookup_field' attribute on this field.</p>
</blockquote>

<p>What I find interesting is that the kwargs for the first exception is <code>{'pk': 1}</code>, not <code>{'id':1}</code>. After some help from chat, someone pointed me to <a href="http://www.django-rest-framework.org/api-guide/generic-views/#genericapiview" rel="nofollow">this</a> piece of information:</p>

<blockquote>
  <p>Note that when using hyperlinked APIs you'll need to ensure that both the API views and the serializer classes set the lookup fields if you need to use a custom value.</p>
</blockquote>

<p>This is useful as <code>User</code> serializer extends <code>HyperlinkedModelSerializer</code>:</p>

<pre><code>from rest_framework import serializers

from django.contrib.auth.models import User

from snippets.models import Snippet

class UserSerializer(serializers.HyperlinkedModelSerializer):
    snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)

    class Meta:
        model = User
        fields = ('url', 'id', 'username', 'snippets')
</code></pre>

<p>the <code>User</code> model and serializer has a reverse relationship with <code>Snippet</code>. Now, when I add <code>lookup_field='id'</code> to snippets attribute of <code>UserSerializer</code> (<code>snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True, lookup_field='id')</code>), like it asks me to do so <a href="http://www.django-rest-framework.org/api-guide/serializers/#how-hyperlinked-views-are-determined" rel="nofollow">here</a>, the error is persistent.</p>

<p>What am I doing incorrectly? What can I do to fix this? Is it not having anything to do with <code>lookup_id</code>?</p>

<p>I understand that I could replace <code>&lt;id&gt;</code> with <code>&lt;pk&gt;</code> in my urlpatterns, but I would like to understand <em>why</em> this is happening. Thank you for any help.</p>

<p>I eventually fixed my second exception by printing the serializer in the Django shell/python interactive console. The result I got was this:</p>

<pre><code>&gt;&gt;&gt; from snippets.serializers import UserSerializer
&gt;&gt;&gt; print(UserSerializer())
UserSerializer():
    url = HyperlinkedIdentityField(view_name='user-detail')
    id = IntegerField(label='ID', read_only=True)
    username = CharField(help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, validators=[&lt;django.contrib.auth.validators.UnicodeUsernameValidator object&gt;, &lt;UniqueValidator(queryset=User.objects.all())&gt;])
    snippets = HyperlinkedRelatedField(lookup_field='id', many=True, read_only=True, view_name='snippet-detail')
</code></pre>

<p>It turns out that to change <code>&lt;pk&gt;</code> to <code>&lt;id&gt;</code> in urlspatterns, you need to add <code>url = HyperlinkedIdentityField(view_name='user-detail', lookup_field='id')</code> in the <code>UserSerializer</code> class. </p>

python django rest hyperlink django-rest-framework