2

I want to build a simple API and picked up Django REST Framework (DRF). I want to minimize path nesting as Tom Christie (the author of DRF) pointed out to me.

There are two models: Article and Comment.
For these I want to build the following API paths (with create [C], read [R] and update [U] access):

/                      [R]
/articles/             [R]
/articles/:id/         [R]
/articles/:id/comments [R]
/comments/             [CRU]
/comments/:id          [R]

models.py:

class Article(models.Model):
    text = models.CharField(max_length=140, blank=False)
    recorded_at = models.DateTimeField(blank=False)
    modified_at = models.DateTimeField(auto_now_add=True)


class Comment(models.Model):
    message = models.CharField(max_length=140, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now_add=True)
    article = models.ForeignKey('Article', default=1, related_name='article')

serializers.py:

class ArticleSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Article


class CommentSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Comment

views.py:

class ArticleViewSet(mixins.RetrieveModelMixin,
                     mixins.ListModelMixin,
                     viewsets.GenericViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer


class CommentViewSet(mixins.CreateModelMixin,
                     mixins.RetrieveModelMixin,
                     mixins.ListModelMixin,
                     viewsets.GenericViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer

urls.py:

router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
router.register(r'comments', CommentViewSet)


urlpatterns = patterns('',
    url(r'^', include(router.urls)),
)

The path at root level work:

/                      [R]
/articles/             [R]
/articles/:id/         [R]
/comments/             [CRU]
/comments/:id          [R]

However the nested path returns 404.

/articles/:id/comments [R]
Community
  • 1
  • 1
JJD
  • 50,076
  • 60
  • 203
  • 339

1 Answers1

1

You'll need something like this on your ArticleViewSet...

@detail_route(methods=['get'])
def comments(self, request, pk=None):
    article = self.get_object()
    comments = article.comment_set.all()
    serializer = CommentSerializer(comments)
    return Response(serializer.data)
Tom Christie
  • 33,394
  • 7
  • 101
  • 86
  • The path `articles/:id/comments` renders when I remove `related_name='article'` and use `serializer = CommentSerializer(comments, context={'request': request}, many=True)`. Now only the breadcrumb states the wrong name: `Article` instead `Comment`. – JJD Mar 23 '15 at 16:51
  • "Now only the breadcrumb states the wrong name: Article instead Comment." That's going to stay the same way unless you want to have a dig into overriding the template (I wouldn't especially recommend that') - I'd probably just live with it at that point. – Tom Christie Mar 23 '15 at 16:56
  • Now that you telling I remember that I read somewhere that detail views do not render the correct object title. Thank you. – JJD Mar 23 '15 at 17:21