Как передать словарь в url в POST-запросе в Python
Мне нужно получить информацию о товарных запасах из API торговой площадки через POST-запрос. API требует передавать в url идентификаторы товаров (sku). Пример: https://api.market.com/campaigns/{campaignId}/warehouse/{warehouseId}/stocks/actual.json?sku=sku1&sku=sku2&sku=sku3. Так что я полагаю, что мне нужно передать дикту типа {'sku': '1', 'sku': '2', 'sku': '3'}. Но, конечно, невозможно создать dict с одинаковыми ключами. Я не знаю, как решить эту задачу. Я сделал функцию, использующую urllib (urlencode), которая работает. Но она создает url только с последним элементом в params. params = {"sku": "ps-22-1", "sku2": "ps-22-7-2", "sku3": "ps-22-7-3"}
def get_stocks(self, campaign_id, warehouse_id, sku):
""" Method for parse stocks
Parameters:
campaign_id (int): client_id in Store
warehouse_id (int): warehouse_id in Warehouse
sku (str): product sku in Product
Returns:
data (json): JSON with stocks data """
url = f"{self.url}campaigns/{campaign_id}/warehouses/{warehouse_id}/stocks/actual.json?"
req = requests.get(url + urllib.parse.urlencode(sku),
headers=self.headers)
if req.status_code == 200:
return True, '200', req.json()
return False, req.json()["error"]["message"]
Я храню идентификаторы товаров в своей БД в такой модели:
class Product(models.Model):
name = models.CharField(max_length=150)
sku = models.CharField(max_length=10)
В вашем коде замените эти строки
req = requests.get(url + urllib.parse.urlencode(sku),
headers=self.headers)
с
payload = {"sku": "ps-22-1", "sku2": "ps-22-7-2", "sku3": "ps-22-7-3"}
req = requests.get('url', params=payload, headers=self.headers)
Создайте словарь, который содержит весь список идентификаторов продуктов (sku), затем передайте его через запрос как данные, как показано ниже:
def get_stocks(self, campaign_id, warehouse_id, sku):
""" Method for parse stocks
Parameters:
campaign_id (int): client_id in Store
warehouse_id (int): warehouse_id in Warehouse
sku (str): product sku in Product
Returns:
data (json): JSON with stocks data """
url = f"{self.url}campaigns/{campaign_id}/warehouses/{warehouse_id}/stocks/actual.json?"
data = {"sku_ids":["ps-22-1","ps-22-7-2","ps-22-7-3"]}
req = requests.get(url + urllib.parse.urlencode(sku),
headers=self.headers,
data=data)
if req.status_code == 200:
return True, '200', req.json()
return False, req.json()["error"]["message"]
Для фильтрации нескольких значений необходимо внести изменения и в API. В приведенном ниже примере я использую SqlAlchemy ORM. Вы можете изменить свой в соответствии с вашим ORM.
data = request.data()
session().query(Product).filter(Product.sku.in_(data['sku_ids'])).all()
Я решил эту проблему. Сложность заключалась в том, что skus нужно было брать из базы данных и подставлять динамически. Я беру каждый sku и его значение из базы данных, формирую список dicts и передаю его в метод get_stocks. Итак, это работает:
def get_stocks(self, campaign_id, warehouse_id, sku):
url = f"{self.url}campaigns/{campaign_id}/warehouses/{warehouse_id}/stocks/actual.json?"
sku_list = []
for e in sku:
parsed_sku = urllib.parse.urlencode(e)
sku_list.append(parsed_sku)
s = '&'.join(sku_list)
try:
req = requests.get(url + s,
headers=self.headers)
if req.status_code != 200:
logger.warning(f"Yandex API returned "
f"{req.status_code}")
return []
return req.json()
except (Timeout, HTTPError, Exception) as e:
logger.warning(f"{e}, {e.__class__}")