Странное поведение Django Querydict: объединяет словарь POST в один ключ - PullRequest
5 голосов
/ 11 июня 2011

Я испытываю очень странное поведение при использовании тестового клиента в django.

Я использую POST для отправки данных в мое приложение django.Я обычно делаю это из приложения для iPhone и / или из тестовой HTML-формы.На стороне сервера это то, как я справляюсь:

def handle_query(request):
   print request
   q = con.QueryLog()
   q.ID = request.POST.get('ID', '')
   q.device = request.POST.get('device-model', '')
   ....

Этот оператор печати выглядит так, как вы ожидаете, то есть каждый параметр в запросе на публикацию превращается в ключ в словаре:

POST: QueryDict: {u'app-version ': [u'3.0'], u'server-version ': [u'v3d0'],

Однако я начал писать некоторые тесты, используяТестовый клиент Django, и что бы я ни пытался, словарь параметров POST, которые я отправляю в запросе post, объединяется в один ключ в QueryDict.Позвольте мне проиллюстрировать это следующим кодом:

class SearchTest (TestCase): def setUp (self): pass

def test_search(self):
    request = HttpRequest()
    data = '{"amzn_locale": "com"}'
    # request._raw_post_data = data
    resp = self.client.post(
        '/is/', 
        data=data,
        content_type='application/x-www-form-urlencoded',
        # content_type='application/json',
        )

Тот же оператор печати на стороне сервера показывает необъяснимую группировкусловарь в строку:

POST: QueryDict: {u'{"amzn_locale":"com"}': [u'']}>,

Если я установлю данные для фактического словаря, то же самое

data = {"amzn_locale": "com"}

Установка request._raw_post_data ничего не изменит.Кроме того, изменение

content_type='application/json'

Любая помощь будет высоко ценится.Из этого вопроса stackoverflow кажется, что я не первый, кто сталкивается с этим POST-запросом iphone Json к серверу Django создает QueryDict в QueryDict

Ответы [ 3 ]

7 голосов
/ 12 июня 2011

Проблема в том, что вы предоставляете content_type. Так как вы сделали это, клиент ожидает строку в кодировке urlen, например

"username=hi&password=there&this_is_the_login_form=1"

вместо словаря типа

{'username': 'hi', 'password': 'there', 'this_is_the_login_form': 1}

Если вы удалите kwarg content_type, все будет в порядке.

Редактировать: Оказывается, тестовый клиент будет искать строку в кодировке URL, если вы передадите любой тип содержимого, отличный от MULTIPART_CONTENT - тип содержимого будет использоваться только для определения того, какой набор символов использовать кодировать эту строку в кодировке URL. Это задокументировано здесь . Соответствующий бит гласит:

Если вы предоставите content_type (например, text / xml для полезной нагрузки XML), содержимое данных будет отправлено как есть в запросе POST, используя content_type в заголовке HTTP Content-Type.

Если вы не предоставите значение для content_type, значения в данных будут передаваться с типом содержимого multipart / form-data. В этом случае пары ключ-значение в данных будут кодироваться как составное сообщение и использоваться для создания полезных данных POST.

1 голос
/ 12 июня 2011

Редактировать: И, конечно, прямо в строке выше той, на которую я начал смотреть, правильный ответ. post_data обрабатывается по-разному в зависимости от content_type. Смотрите ответ ниже. Нет необходимости применять изменения ниже.

Похоже, происходит то, что данные, которые вы передаете в публикацию, сразу же сглаживаются функцией кодирования строки в строковое представление, которое QueryDict позже не может прочитать. Я не знаю, каково это предполагаемое поведение, но если вы будете кодировать почтовые данные до того, как они будут сериализованы, то они должны по крайней мере прибыть в требуемой форме в QueryDict. В django / test / client.py мы видим строку 244

post_data = smart_str(data, encoding=charset)

, который просто выравнивает диктовку и сериализует ее. Возможное исправление заключается в применении того же форматирования, что и в GET, перед сериализацией, следовательно,

post_data = smart_str(urlencode(data, doseq=True), encoding=charset)

Мне это кажется разумным, хотя я не могу гарантировать, что это не повлечет за собой последствий в других местах. Похоже, что вы могли бы выполнить вышеупомянутое преобразование в своем коде до вызова client.post, но я не проверял это.

0 голосов
/ 11 июня 2011

Но вы объявили это как строку - у вас есть одинарные кавычки вокруг значения для data.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...