djangodjango-rest-frameworklookup-field

`lookup_field` doesn't work on `ListAPIView`


I am creating a reddit clone.

models.py

class Subreddit(models.Model):
    owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='subreddits')

class Post(models.Model):
    owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING)
    title = models.CharField(max_length=300)
    subreddit = models.ForeignKey(Subreddit, on_delete=models.CASCADE)

urls.py

urlpatterns = [
    # API Views
    # SUBREDDIT VIEWS
    path('r/', ListSubreddits.as_view(), name='reddits'),
    path('r/<int:r_id>/', DetailSubreddit.as_view(), name='reddits-detail'),
    path('r/<int:r_id>/posts/', ListPostsOfReddit.as_view(), name='reddit-posts'), 
]

ListPostsOfReddit

class ListPostsOfReddit(ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    lookup_field = 'subreddit__id'
    lookup_url_kwarg = 'r_id'

I am having a problem with the url named 'reddit-posts'. This url tries to get all a particular subreddit whose id is specified in the url as r_id. The problem here is I am getting all the posts and not the posts specific to that subreddit. So if I have 2 posts in subreddit of id=1 and 3 posts of subreddit of id=2, if i goto r/1/posts/, in theory, I should get only 2 posts but practically I am getting all the 5 posts. I have specified the lookup_field and lookup_url_kwarg but that doesn't seem to work. Need help! Thanks!


Solution

  • Apparently, the docs say that you would need to write the filtering yourself for ListAPIView. See also this similar question.

    In your case, that would look like this:

    class ListPostsOfReddit(ListAPIView):
        serializer_class = PostSerializer
    
        def get_queryset(self):
            return Post.objects.filter(subreddit__id=self.kwargs['r_id'])
    

    As far as I understand the docs for the generic API views, the lookup_field and lookup_url_kwarg attributes are used only in the detail views, not the list views.