Как обрабатывать 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для параметра был возвращен питон myvar, а затем выполните что-то вроде этого:

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

Однако, когда вы попытаетесь получить только последнее значение, переданное в URL-адресе, то есть в приведенном выше примере вы получите 567 , а результат в оболочке будет:

5
6
7

Однако, когда вы делаете распечатку, request.GETкажется, что у него есть listie:

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

Хорошо, обновление: он предназначен для возврата последнего значения, мой вариант использования - мне нужен список.

из django docs:

QueryDict. getitem (key) Возвращает значение для данного ключа. Если ключ имеет более одного значения, getitem () возвращает последнее значение. Вызывает ошибку django.utils.datastructures.MultiValueDictKeyError, если ключ не существует. (Это подкласс стандартного Python KeyError, поэтому вы можете придерживаться перехвата KeyError

QueryDict.getlist (key) Возвращает данные с запрошенным ключом в виде списка Python. Возвращает пустой список, если ключ не существует. Гарантированно вернет какой-то список.

Обновление: если кто-то знает, почему разработчики django сделали это, дайте мне знать, кажется нелогичным отображать список, и он не ведет себя как один. Не очень питонический!

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

Ответы:

181

Вам нужна функция getlist () объекта GET:

request.GET.getlist('myvar')
AndrewF
источник
10
Вам может потребоваться добавить "[]" в конец имени переменной, если вы используете jquery для отправки элементов обратно.
Дэнни Стейпл
2
Я знал о getlist, но "[]" сбил меня с толку. Кроме того, у меня есть друг по имени Энди Стейпл, и на секунду мне показалось, что он знает о Django намного больше, чем я думал. Меня это тоже бросило.
kungphu
1
Это должно быть размещено во всей документации Django, документации Django Rest Framework и наоборот, у меня на лбу. Это действительно застало меня врасплох
Энтони Мэннинг-Франклин,
Похоже, что Django упал на этом, не уверен, что задумал
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&...
Томислав Урбан
источник