Why does Django REST Framework Router break query parameter filtering?

146 Views Asked by At

In the Django REST Framework Tutorial quickstart, views are added to the default router:

// project/urls.py
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)

My project layout is

project/
    stuffs/

I include the stuffs application in the default router:

router.register(r'stuffs', views.StuffViewSet)

The stuffs/ endpoint is then nicely listed in the API Root list of endpoints:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "users": "http://localhost:8000/users/",
    "groups": "http://localhost:8000/groups/",
    "stuffs": "http://localhost:8000/stuffs/"
}

A Stuff object has a relationship to a owner model class and to filter for objects belonging to a certain owner, I intend to use a request such as:

stuffs/?owner_id=abc

In order to do so, and here is where I'm not sure if it is correct, I introduced an urls.py configuration in the stuffs app:

// stuffs/urls.py
urlpatterns = format_suffix_patterns([
    path('stuffs/', stuffs_views.StuffList.as_view()),
    path('stuffs/<int:pk>/', stuffs_views.StuffDetail.as_view()),
    re_path(r'^stuffs/(?P<owner_id>.+)$', stuffs_views.StuffsList.as_view())
])

using the below StuffsList class based view:

class StuffList(generics.ListCreateAPIView):
    serializer_class = StuffSerializer
    def get_queryset(self):
        queryset = Stuff.objects.all()
        owner_id = self.request.query_params.get('owner_id')
        if owner_id is not None:
            queryset = queryset.filter(owner__owner_id=owner_id)
        return queryset

I'm pretty sure this view is correct, because when I remove the View Set from the default router, the query works.

However, when the viewset is registered in the default router, when requesting stuffs/?owner_id=abc the filter is not applied.

I would like to have the viewset in the list of endpoints but at the same time be able to filter using the query parameter. How can I do that?

1

There are 1 best solutions below

2
Ashraful Islam On

Why are you trying with short_id ? Anyway Try this:

def get_queryset(self):
    queryset = Stuff.objects.all()
    owner_id = self.request.query_params.get('owner_id')
    if owner_id is not None:
        queryset = queryset.filter(owner__short_id=int(owner_id))
    return queryset