Python请求POST进行GET?

时间:2014-10-01 19:36:03

标签: python django python-requests

我正在使用Python 2.7.5,Django 1.7,请求2.4.1,并进行一些简单的测试。但是,似乎当我调用requests.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'
}

我没有创建一个新的目标(正如预期的那样),而是获得了目标列表(我对GET的期望)。使用pdb,我看到:

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

这是怎么翻转的?我之前使用过Python请求库没有任何问题,所以我不确定我是否遗漏了一些明显的东西或者是否(使用较新版本的Django / Requests)我必须设置另一个参数?这是一个缓存问题吗?任何调试技巧?我已经尝试重新安装请求,并将Django回滚到1.6.5,但没有任何作用......必须简单。 - 谢谢!

======更新1 ========

只需合并Martijn在此提出的一些调试信息:

(Pdb) requests.post.__name__
'post'

进入requests / api.py&gt; post()定义:

(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)

深入研究request()方法:

(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,但我的resp是一个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.

2 个答案:

答案 0 :(得分:13)

要明确的是,只要请求收到重定向(具有某个status code),我们就必须对请求执行某些转换。

在这种情况下,当您看到非常意外的情况时,最好的调试技巧是使用allow_redirects=False重试您的请求。这将立即返回30x响应。或者,您也可以查看r.history以查看是否有任何30x响应被跟踪。在这种情况下,您可能会看到类似

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

我们知道这样做会导致用户出现意外行为(正如您刚才所做的那样),但这是在网络上操作的唯一正确方法。

我希望这可以帮助您理解为什么这超出了它是一个重定向的事实,并希望它将为您和其他人提供将来调试它的工具。

答案 1 :(得分:9)

感谢Martijn的一些调试技巧!问题是RESTful API将我从http://重定向到https://,导致库返回&#34; second&#34;请求(GET)......