2012-01-10 9 views
13

Estoy implementando una biblioteca de cliente para una HTTP-API privada usando python requests. La API (que no controlo) espera que los parámetros estén en cierto orden, pero python-requests no respeta un dict ordenado como parámetro.python-requests: order get parameters

Esto es lo que he intentado:

import requests 
from django.utils.datastructures import SortedDict 

params = SortedDict() 
params['s'] = 'value1' 
params['f'] = 'value2' 

requests.get('https://example.org/private_api', params=params) 
#performs request as https://example.org/private_api?f=value1&s=value2 

Esto es lo que estoy tratando de evitar:

requests.get('https://example.org?{0}'.format(urlencode(params))) 
+0

¿Por qué usa 'data' param en lugar de' params' cuando realiza la solicitud? –

+0

@Piotr Dobrogost: Eso fue un error cuando compilé el ejemplo. – tback

+0

¿Por qué es esto un problema? Los parámetros GET generalmente se acceden por nombre, no por orden. –

Respuesta

9

solicitudes Actualmente no permiten hacer esto como desee. Esto es por supuesto defecto que será fixed. Sin embargo, como params parámetro puede tener no sólo diccionario pero bytes, así que debería ser capaz de hacer algo en el medio:

from collections import OrderedDict 
from urllib import urlencode 
import requests 

params = OrderedDict([('first', 1), ('second', 2), ('third', 3)]) 
requests.get('https://example.org/private_api', params=urlencode(params)) 

Esto no funciona como veo debido al error en la línea 85 de models.py: self.params = dict(params or [] . Levanté este problema en cuestión Wrong handling of params given as bytes object

+0

Gracias, finalmente marqué esto como la solución, ya que proporciona la solución que se aplica en el futuro previsible. – tback

+0

@TillBackhaus Ya [fijo] (https://github.com/kennethreitz/requests/commit/9e953f33209545bbbd338e06fb2abc2c62c13212). –

+0

¿Para qué sirve esta versión? Cuando lo probé en '1.2.3' y' 2.0.0', 'requests.get ('http://example.org/private_api', params = urlencode (params)). Request.body' devuelto' None ' – Jian

1

Línea 85 de requests/models.py (link) se convierte en el objeto params una llanura dict, en lugar de la SortedDict que se ha pasado. No creo que usted será capaz de hacer lo que quiera , a menos que parchees la biblioteca.

self.params = dict(params or []) 
+0

Considerando las opciones en Creo que tendré que ir con lo que estaba tratando de evitar en ese momento. Gracias. – tback

17

Las solicitudes lib ahora soporta esta fuera de la caja: Para obtener los parámetros ordenados utiliza una secuencia de dos valiosos-tuplas en su lugar. Esto elimina el requisito adicional de OrderedDict.

payload = (('key1', 'value1'), ('key2', 'value2')) 
r = requests.get("http://httpbin.org/get", params=payload) 

Demostración:

>>> import requests 
>>> requests.__version__ 
1.2.3 
>>> payload = (('key1', 'value1'), ('key2', 'value2'), ('key3', 'value3')) 
>>> r = requests.get("http://httpbin.org/get", params=payload) 
>>> print r.json()['url'] 
http://httpbin.org/get?key1=value1&key2=value2&key3=value3 
0

he encontrado que esto funciona en 1.2.3, así como 2.0.0

>>> import requests 
>>> requests.__version__ 
'2.0.0' 
>>> data = [('first', 1), ('second', 2), ('third', 3)] 
>>> requests.get('http://example.org/private_api', data=data).request.body 
'first=1&second=2&third=3' 
1

Se utiliza con la versión 2.2.0:

import requests 
yourparams = {'s' : 'value1', 'f': 'value2'} 

test = requests.get('https://example.org/private_api', params=yourparams) 
print(test.url) 

Más detalles? Kindly check in here.

+0

Esto no conserva el orden de params que solicitó OP. –