2014-10-01 3 views
4

Я использую Python 2.7.5, Django 1.7, запросы 2.4.1 и простую проверку. Однако, похоже, когда я вызываю request.post, метод выполняет GET.Python просит POST делать GET?

Мой код, говорящий с RESTful API. Обратите внимание, что команда POST работает через Hurl.it с этой полезной нагрузкой и конечной точкой:

def add_dummy_objective(self): 
    """ 
    To the bank 
    """ 
    payload = { 
     'displayName': { 
      'text': self._test_objective 
     }, 
     'description': { 
      'text': 'For testing of API Middleman' 
     }, 
     'genusTypeId': 'DEFAULT' 
    } 
    obj_url = self.host + self.bank_id + '/objectives/?proxyname=' + self._admin_key 
    req = requests.post(obj_url, data=json.dumps(payload), headers=self.headers) 
    return req.json() 

Я устанавливаю заголовки в формате JSON:

self.headers = { 
    'Content-Type' : 'application/json' 
} 

Вместо того чтобы создавать новую цель (как и ожидалось с POST), Я получаю список целей назад (что я ожидал бы с GET). Используя pdb, я вижу:

(Pdb) req.request 
<PreparedRequest [GET]> 
(Pdb) req.request.method 
'GET' 

Как это перевернулось? Я использовал библиотеку запросов Python раньше без каких-либо проблем, поэтому я не уверен, что у меня что-то неявное или если (с более новыми версиями Django/Requests) мне нужно установить еще один параметр? Это проблема кеширования? Любые советы по отладке? Я попытался переустановить запросы и откат Django до 1.6.5, но ничего не работает ... должно быть просто. -- Благодаря!

====== UPDATE 1 ========

Просто консолидации некоторых из отладочной информации, что Мартейн предложил здесь:

(Pdb) requests.post.__name__ 
'post' 

Шагая в запросы/API. ру> сообщение() определение:

(Pdb) l 
88   :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. 
89   :param \*\*kwargs: Optional arguments that ``request`` takes. 
90   """ 
91   import pdb 
92   pdb.set_trace() 
93 ->  return request('post', url, data=data, **kwargs) 

Бурение вниз в методе запроса():

(Pdb) method 
'post' 
(Pdb) l 
43   >>> req = requests.request('GET', 'http://httpbin.org/get') 
44   <Response [200]> 
45   """ 
46   import pdb 
47   pdb.set_trace() 
48 ->  session = sessions.Session() 
49   return session.request(method=method, url=url, **kwargs) 

еще один слой, в session.request:

(424)request() 
-> method = builtin_str(method) 
(Pdb) method 
'post' 
(Pdb) l 
419    :param cert: (optional) if String, path to ssl client cert file (.pem). 
420     If Tuple, ('cert', 'key') pair. 
421    """ 
422    import pdb 
423    pdb.set_trace() 
424 ->   method = builtin_str(method) 
425 
426    # Create the Request. 
427    req = Request(
428     method = method.upper(), 
429     url = url, 

шагая вниз до конца этого метода, когда запрос на самом деле сделал, мой «приготовительный» является POST, но мой соответственно является GET:

(Pdb) prep 
<PreparedRequest [POST]> 
(Pdb) n 
-> return resp 
(Pdb) resp 
<Response [200]> 
(Pdb) resp.request 
<PreparedRequest [GET]> 
(Pdb) l 
449     'allow_redirects': allow_redirects, 
450    } 
451    send_kwargs.update(settings) 
452    resp = self.send(prep, **send_kwargs) 
453 
454 ->   return resp 
455 
456   def get(self, url, **kwargs): 
457    """Sends a GET request. Returns :class:`Response` object. 
458 
459    :param url: URL for the new :class:`Request` object. 
+0

Код, который вы отправили, будет * не * производить GET, он будет генерировать POST. Вы на 100% уверены, что выполняете правильный код? –

+0

Это часть моего модульного тестирования, и я перехожу через него по строкам, поэтому я на 99% уверен, что это путь к коду, который он следует, - если есть какой-то другой способ проверить, чтобы устранить этот 1%, я не зная, как, но был бы счастлив сделать это ... – user

+0

Кстати, я согласен и понимаю, что приведенный выше код должен произвести POST ... поэтому я предполагаю, что что-то еще не так (1%). Какие еще способы найти путь, который я выполняю (помимо pdb), если я использую неправильный путь кода? – user

ответ

9

Чтобы быть ясным, всякий раз, когда запросы получают перенаправление (с определенным status code), мы должны выполнить определенные преобразования по запросу.

В таких случаях, когда вы видите что-то очень неожиданное, лучшие советы по отладке - это повторить запрос, но с allow_redirects=False. Это немедленно вернет 30-кратный ответ. Кроме того, вы также можете проверить r.history, чтобы узнать, есть ли ответы на 30x, которые были соблюдены. В этом случае вы, вероятно, увидели бы что-то вроде

>>> r.request.method 
'GET' 
>>> r.history 
[<Response [302]>,] 
>>> r.history[0].request.method 
'POST' 

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

Я надеюсь, что это поможет вам понять, почему это произошло за пределами того факта, что это было перенаправление, и, надеюсь, это даст вам и другим инструментам возможность отладки этого в будущем.

+0

Спасибо за четкое объяснение! Я немного читал о переадресации, когда нашел это, и лучше понимаю, почему библиотека ведет себя так, как она есть ... – user

6

Благодаря Martijn для некоторых советов по отладке! Проблема заключалась в том, что API RESTful перенаправлял меня с http: // на https: //, что заставляло библиотеку возвращать «второй» запрос (GET) ...

Смежные вопросы