How to pass multiple parameters for aiohttp request wit the same name?

Viewed 1937

The API from which I want to receive data takes several values with the same name as a parameter:

https://example.com/method?types=Retail&types=Office&types=Industrial......

I try to do it like this:

params_api_sale = {
    'types': [
        'Retail', 'Office', 'Industrial', 
        'Mixed Use', 'Development Site', 
        'Land', 'Special Purpose', 'Other'
    ],
    'sortDirection': 'Descending',
    'sortOrder': 'ActivatedOn'
}

async def get_items():
    async with aiohttp.request(
        method='GET', url=vars_.url_api_sale, 
        headers=vars_.headers, params=vars_.params_api_sale) as response:
        ...

But this gives me an error:

Traceback (most recent call last):
  File "foo.py", line 85, in <module>
    asyncio.get_event_loop().run_until_complete(main())
  File "C:\Python37\lib\asyncio\base_events.py", line 583, in run_until_complete
    return future.result()
  File "foo.py", line 80, in main
    await asyncio.create_task(get_items())
  File "foo.py", line 44, in get_items
    headers=vars_.headers, params=vars_.params_api_sale) as response:
  File "D:\Dev\venv\lib\site-packages\aiohttp\client.py", line 1051, in __aenter__
    self._resp = await self._coro
  File "D:\Dev\venv\lib\site-packages\aiohttp\client.py", line 473, in _request
    ssl=ssl, proxy_headers=proxy_headers, traces=traces)
  File "D:\Dev\venv\lib\site-packages\aiohttp\client_reqrep.py", line 263, in __init__
    url2 = url.with_query(params)
  File "D:\Dev\venv\lib\site-packages\yarl\__init__.py", line 922, in with_query
    new_query = self._get_str_query(*args, **kwargs)
  File "D:\Dev\venv\lib\site-packages\yarl\__init__.py", line 886, in _get_str_query
    quoter(k) + "=" + quoter(self._query_var(v)) for k, v in query.items()
  File "D:\Dev\venv\lib\site-packages\yarl\__init__.py", line 886, in <genexpr>
    quoter(k) + "=" + quoter(self._query_var(v)) for k, v in query.items()
  File "D:\Dev\venv\lib\site-packages\yarl\__init__.py", line 864, in _query_var
    "of type {}".format(v, type(v))
TypeError: Invalid variable type: value should be str or int, got ['Retail', 'Office', 'Industrial', 'Mixed Use', 'Development Site', 'Land', 'Special Purpose', 'Other'] of type <class 'list'>

I have not found a documented way to do this. All that comes to my mind is to generate a URL string with these parameters, of course, if there is no more correct way.

2 Answers
import requests

params = {
    'types': [
        'Retail', 'Office', 'Industrial',
        'Mixed Use', 'Development Site',
        'Land', 'Special Purpose', 'Other'
    ],
    'sortDirection': 'Descending',
    'sortOrder': 'ActivatedOn'
}

r = requests.get("http://www.test.com/", params=params)

print(r.url)

output:

https://www.test.com/?types=Retail&types=Office&types=Industrial&types=Mixed+Use&types=Development+Site&types=Land&types=Special+Purpose&types=Other&sortDirection=Descending&sortOrder=ActivatedOn

For aiohttp you can use MultiDict which is also included in the official document.

For sending data with multiple values for the same key MultiDict may be used as well.

As stated at aiohttp documentation, you can pass a list of tuples to params with the same key to achieve your goal:

Also it is possible to pass list of 2 items tuples as parameters, in that case you can specifiy multiple values for each key:

params = [
    ("key1", "value1"),
    ("key1", "value2"),
    ("key2", "value3"),
]
Related