2012-01-10 11 views
13

Sto implementando una libreria client per un'API HTTP privata utilizzando python requests. L'API (che non controllo) si aspetta che i parametri siano in un certo ordine, ma le richieste python non rispettano un dettato ordinato come parametro.richieste python: ordine ottenere parametri

Questo è quello che ho provato:

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 

Questo è quello che sto cercando di evitare:

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

Perché si usa il parametro 'data' invece di' params' quando si effettua la richiesta? –

+0

@Piotr Dobrogost: si è trattato di un errore durante la compilazione dell'esempio. – tback

+0

Perché questo è un problema? I parametri GET sono generalmente accessibili per nome e non per ordine. –

risposta

9

richieste Attualmente non permette di fare questo come si desidera. Questa è ovviamente una mancanza che sarà fixed. Tuttavia, come params parametro può assumere dizionario non solo, ma byte, così si dovrebbe essere in grado di fare una via di mezzo:

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

Questo non funziona come la vedo a causa di bug in linea 85 del models.py: self.params = dict(params or [] . ho sollevato questo problema in problema Wrong handling of params given as bytes object

+0

Grazie, ho finalmente contrassegnato questo come la soluzione in quanto fornisce la soluzione che è applicabile nel prossimo futuro. – tback

+0

@TillBackhaus Già [riparato] (https://github.com/kennethreitz/requests/commit/9e953f33209545bbbd338e06fb2abc2c62c13212). –

+0

Per quale versione funziona? Quando l'ho provato in '1.2.3' e' 2.0.0', 'requests.get ('http://example.org/private_api', params = urlencode (params)). Request.body' restituito' None ' – Jian

1

Linea 85 del requests/models.py (link) trasforma l'oggetto params in una pianura dict, piuttosto che il SortedDict avete passato. Io non credo che sarà in grado di fare quello che vuoi , a meno che non si patch la libreria.

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

Considerando le opzioni a penso che dovrò andare con quello che stavo cercando di evitare poi. Grazie. – tback

17

Le richieste lib ora supportano questo out-of-the-box: per ottenere parametri ordinati si utilizza invece una sequenza di tuple a due valori. Ciò elimina il requisito aggiuntivo di OrderedDict.

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

Demo:

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

ho scoperto che questo funziona in 1.2.3 così come 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

Ha usato con la versione 2.2.0:

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

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

Altro dettagli? Si prega di check-in here.

+0

Questo non conserva l'ordine dei parametri che è stato richiesto dall'OP. –