Як обробляти request.GET з кількома змінними для одного і того ж параметра в Django


82

У поданні Django ви можете отримати доступ до request.GET['variablename'], тому у своєму поданні ви можете зробити щось подібне:

myvar = request.GET['myvar']

Фактичний request.GET['myvar']тип об'єкта:

<class 'django.http.QueryDict'>

Тепер, якщо ви хочете передати кілька змінних з однаковим іменем параметра, тобто:

http://example.com/blah/?myvar=123&myvar=567

Ви хотіли б, щоб listдля параметра повернувся python myvar, тоді зробіть щось подібне:

for var in request.GET['myvar']:
    print(var)

Однак, коли ви намагаєтесь отримати лише останнє значення, передане в url, тобто у наведеному вище прикладі ви отримаєте 567 , і результат в оболонці буде:

5
6
7

Однак, коли ви робите друк, request.GETздається, що він має listтобто:

<QueryDict: {u'myvar': [u'123', u'567']}>

Ok Update: Він призначений для повернення останнього значення, у моєму випадку використання мені потрібен список.

з django docs:

QueryDict. getitem (ключ) Повертає значення для даного ключа. Якщо ключ має більше одного значення, getitem () повертає останнє значення. Піднімає django.utils.datastructures.MultiValueDictKeyError, якщо ключ не існує. (Це підклас стандартної KeyError Python, тому ви можете дотримуватися лову KeyError

QueryDict.getlist (ключ) Повертає дані із запитаним ключем у вигляді списку Python. Повертає порожній список, якщо ключ не існує. Гарантовано повернеться якийсь список.

Оновлення: Якщо хтось знає, чому django dev зробили це, будь ласка, дайте мені знати, здається протиінтуїтивним, щоб показати список, і він не поводиться як один. Не дуже пітонічно!


4
Я думаю, що міркування полягають у тому, що ви повинні знати, чи слід очікувати переліку чи індивідуального значення. QueryDict.getitem не повинен інколи повертати список, окремий елемент інший раз - тоді кожному завжди доведеться перевіряти його тип повернення, щоб правильно обробляти його.
jgiles

Відповіді:


181

Вам потрібна функція getlist () об'єкта GET:

request.GET.getlist('myvar')

10
Можливо, вам доведеться додати "[]" в кінець імені var, якщо ви використовуєте jquery для опублікування елементів назад.
Danny Staple

2
Я знав про getlist, але "[]" кинув мене. Крім того, у мене є друг на ім'я Енді Стейпл, і на секунду я подумав, що він знає про Джанго більше, ніж я думав. Це мене також кинуло.
kungphu

1
Це потрібно розміщувати по всіх документах Django, документах Django Rest Framework і назад на моєму лобі. Це мене справді застало несподіваним
Ентоні Меннінг-Франклін,

Здається, Джанго як би кинув м'яч на цей, не впевнений, чи призначений
NaturalBornCamper

1

Іншим рішенням є створення копії об'єкта запиту ... Зазвичай ви не можете перебирати об'єкт request.GET або request.POST, але ви можете робити такі дії з копією:

res_set = request.GET.copy()
for item in res_set['myvar']:
    item
...

2
ти впевнений? це абсолютно не змінює поведінку QueryDict для мене. я просто отримую ще один QueryDict з тим самим "обмеженням"
горіхи

0

При створенні рядка запиту з об'єкта QueryDict, який містить кілька значень для одного і того ж параметра (наприклад, набору прапорців), використовуйте метод urlencode ():

Наприклад, мені потрібно було отримати запит на вхідний запит, видалити параметр і повернути оновлений рядок запиту на отриману сторінку.

# Obtain a mutable copy of the original string
original_query = request.GET.copy()

# remove an undesired parameter
if 'page' in original_query:
    del original_query['page']

Тепер, якщо вихідний запит має кілька значень для одного і того ж параметра, наприклад: {... 'track_id': ['1', '2'], ...} ви втратите перший елемент у рядку запиту під час використання коду подібно до:

new_query = urllib.parse.urlencode(original_query)

призводить до...

...&track_id=2&...

Однак можна використовувати метод urlencode класу QueryDict, щоб правильно включити кілька значень:

new_query = original_query.urlencode()

який виробляє ...

...&track_id=1&track_id=2&...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.