1

I am trying to build an app using the DRF's quickstart guide. The app has the following setup

/school/
/school/<pk>
/school/<pk>/courses/
/school/<pk>/courses/<pk>
/school/<pk>/courses/<pk>/members/

When I follow the quickstart I get the following error

ImproperlyConfigured at /api/v1/school/1/courses/1/members/
Could not resolve URL for hyperlinked relationship using view name "courses-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

when vising

/school/<pk>/courses/<pk>/members/

I don't really understand the error message I am getting as I have the view name "courses-detail" readily available. Could anybody help me clear out what I have done wrong?

This is the code I have in the example application.

views.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets, permissions
from rest_framework.response import Response

from .serializers import SchoolSerializer, SchoolActivitySerializer, SchoolCourseSerializer, CourseSerializer, ActivitySerializer, SchoolCourseMemberSerializer, MemberSerializer
from .models import School, Course, Activity, Member


# Create your views here.
class SchoolViewset(viewsets.ModelViewSet):
    serializer_class = SchoolSerializer
    queryset = School.objects.all()


class CourseViewset(viewsets.ModelViewSet):
    serializer_class = CourseSerializer
    queryset = Course.objects.all()

    def get_school(self, school_pk):
        school = get_object_or_404(School.objects.all(), pk=school_pk)
        return school

    def list(self, request, *args, **kwargs):

        queryset = Course.objects.all()
        serializer = CourseSerializer(queryset, many=True)
        return Response(serializer.data)


class MemberViewset(viewsets.ModelViewSet):
    serializer_class = MemberSerializer
    queryset = Member.objects.all()

class ActivityViewset(viewsets.ModelViewSet):
    serializer_class = ActivitySerializer
    queryset = Activity.objects.all()

    def list(self, request, *args, **kwargs):
        queryset = Activity.objects.filter()
        serializer = ActivitySerializer(queryset, many=True)
        return Response(serializer.data)

class SchoolCourseMemberViewset(viewsets.ModelViewSet):
    serializer_class = SchoolCourseMemberSerializer
    queryset = Member.objects.all()

serializers.py

from rest_framework import serializers
from rest_framework_nested import serializers as nested_serializers
from rest_framework_nested import relations
from .models import School, Course, Activity, Member


class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = ('course_name', 'course_date', 'course_school',)


class ActivitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Activity
        fields = ('activity_name', 'activity_location', 'activity_school', 'activity_date', 'activity_price',)


class MemberSerializer(serializers.ModelSerializer):
    class Meta:
        model = Member
        fields = ('user', 'ranking',)


class SchoolCourseSerializer(nested_serializers.NestedHyperlinkedModelSerializer):
    parent_lookup_kwargs = {
        'school_pk': 'course_school',
    }

    class Meta:
        model = Course
        fields = ('id', 'course_name', 'course_date',)


class SchoolCourseMemberSerializer(nested_serializers.NestedHyperlinkedModelSerializer):
    courses_lookup_kwargs = {
        'school_pk': 'school__pk',
        'course_pk': 'course__pk',
    }
    courses = relations.NestedHyperlinkedRelatedField(parent_lookup_kwargs={'course_school_pk': 'course_school__pk'}, view_name='courses-detail', queryset=Course.objects.all())

    class Meta:
        model = Member
        fields = ('url', 'user', 'ranking', 'courses', )


class SchoolActivitySerializer(nested_serializers.NestedHyperlinkedModelSerializer):

    class Meta:
        model = Activity
        fields = ('activity_name', 'activity_location', 'activity_date', 'activity_price',)


class SchoolMemberSerializer(nested_serializers.NestedHyperlinkedModelSerializer):

    class Meta:
        model = Member
        fields = ('user', 'ranking',)


class SchoolSerializer(serializers.ModelSerializer):

    class Meta:
        model = School
        fields = ('id', 'url', 'school_name', 'school_address', 'courses', 'activities', 'members', )

    courses = SchoolCourseSerializer(many=True, read_only=True)
    activities = SchoolActivitySerializer(many=True, read_only=True)
    members = SchoolMemberSerializer(many=True, read_only=True)

models.py

from __future__ import unicode_literals

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

# Create your models here.
class School(models.Model):
    school_name = models.CharField(max_length=30, verbose_name='Name', help_text="The name of the school.")
    school_address = models.CharField(max_length=30, verbose_name='Address', help_text="The location of the school.")


class Course(models.Model):
    course_name = models.CharField(max_length=30)
    course_date = models.DateTimeField(auto_now_add=True)
    course_school = models.ForeignKey(School, related_name='courses')


class Activity(models.Model):
    activity_name = models.CharField(max_length=30)
    activity_location = models.CharField(max_length=30)
    activity_school = models.ForeignKey(School, related_name='activities')
    activity_date = models.DateTimeField(auto_now_add=True)
    activity_price = models.DecimalField(decimal_places=2, max_digits=11, verbose_name='price')

class Member(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ranking = models.IntegerField(verbose_name='ranking', blank=False)

    #users = User.objects.all().select_related('profile')

@receiver(post_save, sender=User)
def create_user_member(sender, instance, created, **kwargs):
    if created:
        Member.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_member(sender, instance, **kwargs):
    instance.member.save

urls.py

from django.conf.urls import url, include
from rest_framework_nested import routers

from .views import SchoolViewset, CourseViewset, ActivityViewset, MemberViewset, SchoolCourseMemberViewset

router_1 = routers.SimpleRouter()
router_1.register('school', SchoolViewset, base_name='school')
school_router = routers.NestedSimpleRouter(router_1, r'school', lookup='school')
school_router.register(r'activities', ActivityViewset, base_name='activities')
school_router.register(r'courses', CourseViewset, base_name='courses')
school_router.register(r'members', MemberViewset, base_name='members')

school_member_router = routers.NestedSimpleRouter(school_router, r'courses', lookup='courses')
school_member_router.register('members', SchoolCourseMemberViewset, base_name='members')



urlpatterns = [
    url(r'', include(router_1.urls)),
    url(r'', include(school_router.urls)),
    url(r'', include(school_member_router.urls)),
]

If i have failed to include any information needed to resolve the error please do tell me. I will gladly supply any additional information.

Thanks in advance.

N. Dury
  • 3
  • 1
  • 7
  • I have figured out the issue is directly related to the courses field defined on the SchoolCourseMemberSerializer. Commenting the field removes the given error. Still researching on how to do this properly. Will update with further progress. – N. Dury Jun 27 '17 at 16:41

0 Answers0