Захват параметров URL в запросе. GET

458

В настоящее время я определяю регулярные выражения для захвата параметров в URL-адресе, как описано в руководстве. Как мне получить доступ к параметрам из URL как части HttpRequestобъекта? Мой в HttpRequest.GETнастоящее время возвращает пустой QueryDictобъект.

Я хотел бы научиться делать это без библиотеки, чтобы я мог лучше узнать Джанго.

остаться, таких
источник

Ответы:

663

Когда URL-адрес, как:, тоdomain/search/?q=haha вы бы использовать request.GET.get('q', '').

qэто параметр, который вы хотите, и ''значение по умолчанию, если qне найден.

Однако если вы вместо этого просто конфигурируете свойURLconf , то ваши снимки из regexпередаются в функцию в качестве аргументов (или именованных аргументов).

Такие как:

(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),

Тогда в вашем views.pyвы бы

def profile_page(request, username):
    # Rest of the method
camflan
источник
10
Является ли '? Param =' единственным способом, которым Django распознает параметры? Есть ли способ использовать URLconf с HTTP.GET? Я хотел бы сделать / param / 2.
sutee
3
Посмотрите вторую часть моего ответа, касающуюся ваших URLconf и регулярных выражений.
Camflan
2
Нет проблем. используйте request.GET, если вы отправляете форму с помощью GET, используйте request.POST, если вы отправляете форму с помощью POST, и если вы просто хотите настроить URL-адреса, чтобы иметь переменные разделы, то это аргумент URLconf / view.
Camflan
10
А как насчет классов?
Пользователь
8
для представлений на основе классов вы можете использоватьself.kwargs['parameter']
Royendgel Silberie
336

Чтобы уточнить объяснение Camflan, давайте предположим, что у вас есть

  • правило url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
  • входящий запрос на http://domain/user/thaiyoshi/?message=Hi

Правило диспетчера URL будет захватывать части пути URL (здесь "user/thaiyoshi/") и передавать их функции просмотра вместе с объектом запроса.

Строка запроса (здесь message=Hi) анализируется и параметры сохраняются в качестве QueryDictин request.GET. Дальнейшее сопоставление или обработка параметров HTTP GET не производится.

Эта функция просмотра будет использовать как части, извлеченные из пути URL, так и параметр запроса:

def profile_page(request, username=None):
    user = User.objects.get(username=username)
    message = request.GET.get('message')

В качестве примечания вы найдете метод запроса (в данном случае "GET"и обычно для отправленных форм "POST") вrequest.method . В некоторых случаях полезно проверить, что оно соответствует ожидаемому.

Обновление: при принятии решения о том, использовать ли путь URL или параметры запроса для передачи информации, может помочь следующее:

  • используйте путь URL для уникальной идентификации ресурсов, например /blog/post/15/(не /blog/posts/?id=15)
  • использовать параметры запроса для изменения способа отображения ресурса, например, /blog/post/15/?show_comments=1или/blog/posts/2008/?sort_by=date&direction=desc
  • чтобы сделать понятные для человека URL-адреса, избегайте использования идентификационных номеров и используйте, например, даты, категории и / или слагов: /blog/post/2008/09/30/django-urls/
akaihola
источник
17
Это действительно хорошо написанный ответ. Это, конечно, помогло мне понять Джанго немного лучше.
Марк
2
Как мы можем получить все значения параметров без упоминания имен
Numrah
@numerah request.GET - это словарь Python. Например, вы можете перебирать request.GET.items ().
akaihola
идеальный ответ.
Джей
1
какие-либо причины, почему предпочтительнее следовать привычкам, написанным в обновлении? (когда использовать URL-путь против GET-параметров)
m0etaz
55

Используя GET

request.GET["id"]

Использование POST

request.POST["id"]
Дадасо Занзане
источник
27
Хотя это работает для существующих ключей, ответы camflan и akaihola использовали .get (), чтобы избежать KeyErrorисключений в случае отсутствия ключа. Было бы разумно сделать то же самое (например request.POST.get('id', '')).
Огромный супермен
25
def some_view(request, *args, **kwargs):
    if kwargs.get('q', None):
        # Do something here ..
Kevin
источник
21

Для ситуаций, когда у вас есть только тот requestобъект, который вы можете использоватьrequest.parser_context['kwargs']['your_param']

Оле Хенрик Скогстрём
источник
2
Именно то, что мне было нужно. Спасибо.
user4052054
20

Я хотел бы добавить некоторые варианты себя, здесь. Кто-то хотел бы знать, как установить путь в urls.py, например,

domain/search/?q=CA

чтобы мы могли вызвать запрос.

Дело в том, что НЕ нужно устанавливать такой маршрут в urls.py. То, что вам нужно установить, это просто маршрут в urls.py

urlpatterns = [
    path('domain/search/', views.CityListView.as_view()),
]

и когда вы вводите HTTP: // имя_сервера: порт / домен / поиск / д = CA . Часть запроса '? Q = CA' будет автоматически зарезервирована в хеш-таблице, на которую вы можете ссылаться

request.GET.get('q', None).

Вот пример (views.py)

class CityListView(generics.ListAPIView):
    serializer_class = CityNameSerializer

    def get_queryset(self):
        if self.request.method == 'GET':
            queryset = City.objects.all()
            state_name = self.request.GET.get('q', None)
            if state_name is not None:
                queryset = queryset.filter(state__name=state_name)
            return queryset

Кроме того, когда вы пишете строку запроса в URL

http://servername:port/domain/search/?q=CA

Не заключайте строку запроса в кавычки, например

http://servername:port/domain/search/?q="CA"
Эрик Эндрюс
источник
Привет, Эрик! Я новичок в Джанго. Можете ли вы пролить больше света на "queryset = queryset.filter (state__name = state_name)". Что означает двойное подчеркивание в state__name.
Subbu
1
Здесь «состояние» - это таблица, а «имя» - это поле, хранящееся в этой таблице. В фильтре Django имя_состояния будет ссылаться на значение поля "имя" в таблице "состояние".
Эрик Эндрюс
этот работал по сравнению с другими.
Сибиш
17

Я хотел бы поделиться советом, который может сэкономить вам время.
Если вы планируете использовать что-то подобное в своем urls.pyфайле:

url(r'^(?P<username>\w+)/$', views.profile_page,),

Что в основном означает www.example.com/<username>. Обязательно поместите его в конце ваших записей URL, потому что в противном случае, он склонен вызывать конфликты с записями URL , которые следуют ниже, то есть доступ к одному из них будет давать вам ошибку приятно: User matching query does not exist.

я только что пережил это сам; Надеюсь, поможет!

DrKaoliN
источник
2
Кроме того, в этом случае вы можете проверить, не совпадают ли имена пользователей с другими URL-адресами.
DrKaoliN
13

У вас есть два распространенных способа сделать это, если ваш URL выглядит так:

https://domain/method/?a=x&b=y

v1:

Если конкретный ключ является обязательным, вы можете использовать:

key_a = request.GET['a']

Это вернет значение a если ключ существует, и исключение, если нет.

v2:

Если ваши ключи не являются обязательными:

request.GET.get('a')

Вы можете попробовать это без каких-либо аргументов, это не даст сбой. Таким образом, вы можете обернуть его try: except:и вернуться HttpResponseBadRequest()в пример. Это простой способ сделать ваш код менее сложным, без использования специальной обработки исключений.

Бартоломей
источник
Как я могу определить параметр запроса из шаблона?
Акин Хван
8

Это не совсем то , что вы просили, но этот фрагмент является полезным для управления query_stringsв templates.

jamting
источник
5

Эти запросы в настоящее время выполняются двумя способами. Если вы хотите получить доступ к параметрам запроса (GET), вы можете запросить следующее:

http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1

Если вы хотите получить доступ к параметрам, переданным POST, вам нужно получить доступ к этому способу:

request.data.get('role', None)

Получая доступ к словарю (QueryDict) с помощью get (), вы можете установить значение по умолчанию. В вышеупомянутых случаях, если «статус» или «роль» не сообщаются, значения равны None.

mdcg
источник
0

Это еще одно альтернативное решение, которое может быть реализовано:

в конфиге URL. :

urlpatterns = [path('runreport/<str:queryparams>', views.get)]

во взглядах:

list2 = queryparams.split("&")
Сати
источник