Django Rest отправляет параметр в URL в набор запросов

#django-rest-framework #django-urls #url-parameters

#django-rest-framework #django-urls #url-параметры

Вопрос:

Я искал ответ в связанных темах, но ни один из них не работал. Итак, следуя указателю Django Rest Guid о фильтрации, я хотел добавить возможность фильтрации данных по URL.

У меня есть свое мнение:

 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
 

и мой файл urls:

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

]
 

Когда я предоставляю url, например: http://localhost:8000/artists?name=A5 , он показывает, что этот URL не существует.
Я также пытался http://localhost:8000/artists/A5 вернуть всех исполнителей вместо только 1.

Я также пытался re_path('^artists/(?P<name>. )/$', ArtistList.as_view(), name='artists'), , как в примере в руководстве, но все равно получал сообщение об ошибке. Что здесь не так?

У меня также есть второй вопрос. Каков наилучший способ манипулировать URL-адресами с помощью параметров? Я имею в виду, должен ли я объявить первый URL для возврата всего объекта, а второй — только для определенного?

Ответ №1:

Вы путаете две вещи:

  1. у вас есть путь, который часто является частью хоста, и перед строкой запроса строка запроса начинается с ? , поэтому путь для http://localhost:8000/artists?name=A5 artists . Параметры URL помещаются в self.kwargs ; и
  2. у вас есть строка запроса, строка запроса — это коллекция пар ключ-значение, которая начинается после вопросительного знака, в котором хранятся эти элементы request.query_params .

Если вы, таким образом, хотите фильтровать с /artists/A5 помощью, тогда вы работаете с:

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

class ArtistList(generics.ListAPIView):
    serializer_class = ArtistSerializer

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

В этом случае вам всегда нужно указывать имя, поскольку, как вы выяснили, его непредоставление вернет ответ HTTP 404.

Если вы хотите использовать строку запроса, вы меняете путь на:

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

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

и затем вы используете self.query_params , как уже делали. В этом случае name=… часть не требуется.

Комментарии:

1. Спасибо, вы снова помогаете… Это работает, но вместо localhost:8000/artists?name=A5 я получаю localhost:8000/artists/?name=A5 и удаление косой черты не работает

2. @Frendom: это может быть APPEND_SLASH настройкой ( docs.djangoproject.com/en/3.1/ref/settings/#append-slash ), или браузер, поскольку обычно они должны быть эквивалентны.

3. Я не хочу создавать аналогичный вопрос, но что, если мы захотим добавить еще один параметр (amp;) и использовать его для сортировки моих данных?

4. @Frendom: затем вы снова принимаете этот параметр self.query_params.get('otherparam') . Он автоматически декодирует ?...=...amp;...=...amp;....=... объект, подобный словарю.

Ответ №2:

Если вы хотите использовать ссылку http://localhost:8000/artists?name=A5 , просто переименуйте свой путь :

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

]
 

Если вы хотите использовать http://localhost:8000/artists/A5 , используйте не query_params, а kwargs :

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

В обоих случаях, если вы хотите вернуть один объект, вы можете захотеть перейти к подробному просмотру. (Использование kwargs обычно связано с представлением сведений)