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?
You are mixing up two things:
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
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.