Home > Software design >  How to pass a dictionary to an url in POST request in Python
How to pass a dictionary to an url in POST request in Python

Time:12-09

I have to get information about product stocks from marketplace's API via POST request. API requires to send products IDs (sku) in url Example: https://api.market.com/campaigns/{campaignId}/warehouse/{warehouseId}/stocks/actual.json?sku=sku1&sku=sku2&sku=sku3 So I guess, I have to pass a dict like {'sku': '1', 'sku': '2', 'sku': '3'} But of course, It's impossible to create a dict with same keys. I don't know how to solve this task. I made a function, using urllib (urlencode) that works. But it create an url with only last element in 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"]

I keep products IDs in my DB in such model:

class Product(models.Model):
name = models.CharField(max_length=150)
sku = models.CharField(max_length=10)

CodePudding user response:

In your code, replace these lines

req = requests.get(url   urllib.parse.urlencode(sku), 
                   headers=self.headers)

with

payload = {"sku": "ps-22-1", "sku2": "ps-22-7-2", "sku3": "ps-22-7-3"}
req = requests.get('url', params=payload, headers=self.headers)

CodePudding user response:

Create a dictionary which contains all the list of products IDs (sku), then pass it through the request as data, like shown below:

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

And You have to make the changes in the API too, to filter multiple values. In the below example, I am using SqlAlchemy ORM. You can change yours according to your ORM.

data = request.data()
session().query(Product).filter(Product.sku.in_(data['sku_ids'])).all()

CodePudding user response:

I solved the problem. The difficulty was that the skus needed to be taken from the database and substituted dynamically. I take each sku and its value from the database, form a list of dicts and pass it to the get_stocks method. So, this works:

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__}")
  • Related