mlissner
mlissner

Reputation: 18166

Can't create HyperlinkedRelatedField in Django Rest Framework

I'm struggling to get HyperlinkedRelated fields working, and I can't figure out where I'm going wrong. No matter what I do, I get an error like:

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

I feel that I've tried everything and I don't know where my error could be, nor how to identify it. My reading of this error message is that I am looking for a URL that corresponds to the court-detail view, but that that view doesn't exist.

Some piece of magic isn't working and any help would be greatly appreciated.

URLs:

from cl.api import views

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'courts', views.CourtViewSet)
router.register(r'dockets', views.DocketViewSet)

router.register(r'clusters', views.OpinionClusterViewSet)
router.register(r'opinions', views.OpinionViewSet)
router.register(r'cited-by', views.OpinionsCitedViewSet)

urlpatterns = [
    # url(r'^api/rest/(?P<version>[v3]+)/', include(router.urls)),
    url(r'^api-auth/',
        include('rest_framework.urls', namespace='rest_framework')),
    url(r'^', include(router.urls)),
]

Views:

class DocketViewSet(viewsets.ModelViewSet):
    queryset = Docket.objects.all()
    serializer_class = serializers.DocketSerializer


class CourtViewSet(viewsets.ModelViewSet):
    queryset = Court.objects.all()
    serializer_class = serializers.CourtSerializer


class OpinionClusterViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    queryset = OpinionCluster.objects.all()
    serializer_class = serializers.OpinionClusterSerializer


class OpinionViewSet(viewsets.ModelViewSet):
    queryset = Opinion.objects.all()
    serializer_class = serializers.OpinionSerializer


class OpinionsCitedViewSet(viewsets.ModelViewSet):
    queryset = OpinionsCited.objects.all()
    serializer_class = serializers.OpinionsCitedSerializer

Serializers:

from cl.audio import models as audio_models
from cl.search import models as search_models

from rest_framework import serializers


class DocketSerializer(serializers.HyperlinkedModelSerializer):
    court = serializers.HyperlinkedRelatedField(
        many=False,
        view_name='court-detail',
        read_only=True
    )

    class Meta:
        model = search_models.Docket
        fields = ('date_created', 'date_modified', 'date_argued',
                  'date_reargued', 'date_reargument_denied', 'court')


class CourtSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = search_models.Court

class AudioSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = audio_models.Audio


class OpinionClusterSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = search_models.OpinionCluster
        fields = ('judges', 'per_curiam', )


class OpinionSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = search_models.Opinion
        fields = ('pk',)


class OpinionsCitedSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = search_models.OpinionsCited

When I go to:

http://127.0.0.1:8000/dockets/

It tells gives me the error message above. Of course, if I remove the court reference from the serialization, it works fine...

Upvotes: 1

Views: 786

Answers (1)

mlissner
mlissner

Reputation: 18166

I imagine this can be caused by a number of things, but in my case, I figured out that it was caused by having DEFAULT_VERSIONING_CLASS set without having it configured in the urls.py:

REST_FRAMEWORK = {
    # Use URL-based versioning
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
    'DEFAULT_VERSION': 'v3',
    'ALLOWED_VERSIONS': {'v3'},
}

The solution, therefore, was either to disable it in the settings, or to set up a url in in urls.py that accepted the version parameter:

url(r'^api/rest/(?P<version>[v3]+)/', include(router.urls)),

Ugh. Took a long time to realize I had this setting in place. Bad error message.

Upvotes: 1

Related Questions