Frendom
Frendom

Reputation: 558

Django Rest sending param in url to queryset

I was looking for answer in related topics, but none was working. So following Django Rest Guid about filtering I wanted to add posibility to filter data via url.

I have my view:

class ArtistList(generics.ListAPIView):
    serializer_class = ArtistSerializer

    def get_queryset(self):
        queryset = Artist.objects.all()
        name = self.request.query_params.get('name', None)
        print(name)
        if name is not None:
            queryset = queryset.filter(name=name)
        return queryset

and my urls file:

urlpatterns = [
...
path('artists/<str:name>', ArtistList.as_view(), name='artists'),    

]

When I provide url like: http://localhost:8000/artists?name=A5 it's showing that this url doesn't exist. I also was trying http://localhost:8000/artists/A5 which lead to returning all artists instead of only 1.

I also was trying re_path('^artists/(?P<name>.+)/$', ArtistList.as_view(), name='artists'), like in the example in guide, but I still was getting an error. What is wrong here?

I have also second question. What is the best way to manipulate urls with params? I mean should I declare first url for returning all object and second for only specifc one?

Upvotes: 0

Views: 1552

Answers (2)

Guillaume
Guillaume

Reputation: 2006

If you want to use the link http://localhost:8000/artists?name=A5 just rename your path :

urlpatterns = [
...
path('artists', ArtistList.as_view(), name='artists'),    

]

If you want to use http://localhost:8000/artists/A5, don't use query_params but kwargs :

name = self.kwargs.get('name', None)

In both cases, if you want to return a single object you might want to go for a detail view. (Using kwargs is usually associated with details view)

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477598

You are mixing up two things:

  1. you have the path which is the part often the host and before the querystring, the querystring starts with ?, so the path for http://localhost:8000/artists?name=A5 is artists. The URL parameters are placed in self.kwargs; and

  2. you have the querystring the querystring is a key-value pair collection that starts after the question mark, these items are stored in request.query_params.

If you thus want to filter with /artists/A5, then you work with:

# http://localhost:8000/artists/A5

class ArtistList(generics.ListAPIView):
    serializer_class = ArtistSerializer

    def get_queryset(self):
        return Artist.objects.filter(name=self.kwargs['name'])

In that case you always need to provide a name, since not providing one will, as you found out, return a HTTP 404 response.

If you want to use the querystring, you change the path to:

# http://localhost:8000/artists?name=A5

urlpatterns = [
    # …,
    path('artists/', ArtistList.as_view(), name='artists'),    
]

and then you use self.query_params like you already did. In that case the name=… part is not required.

Upvotes: 1

Related Questions