Ruserhelper
Ruserhelper

Reputation: 61

Obtain all Woocommerce Orders via Python API

I'm looking to export all orders from the WooCommerce API via a python script.

I've followed the authentication process and I have been using method to obtain orders described here. My code looks like the following:

wcapi = API(
        url = "url",
        consumer_key = consumerkey,
        consumer_secret = consumersecret
)
r = wcapi.get('orders')
r = r.json()
r = r['orders']
print(len(r))        # output: 8

This outputs the most recent 8 orders, but I would like to access all of them. There are over 200 orders placed via woocommerce right now. How do I access all of the orders?

Please tell me there is something simple I am missing. My ultimate goal is to pull these orders automatically, transform them, and then upload to a visualization tool. All input is appreciated.

Upvotes: 5

Views: 5510

Answers (3)

autopoietic
autopoietic

Reputation: 197

I encountered the same problem with paginated response for products.

I built on the same approach described by @gtopal, whereby the X-WP-TotalPages header returned by WooCommerce is used to iterate through each page of results.

I knew that I would probably encounter the same issue for other WooCommerce API requests (such as orders), and I didn't want to have to confuse my code by repeatedly performing a loop when I requested a paginated set of results.

To avoid this I used a decorator to abstract the pagination logic, so that get_all_wc_orders can focus just on the request.

I hope the decorator below might be useful to someone else (gist)

from woocommerce import API

WC_MAX_API_RESULT_COUNT = 100

wcapi = API(
    url=url,
    consumer_key=key,
    consumer_secret=secret,
    version="wc/v3",
    timeout=300,
)

def wcapi_aggregate_paginated_response(func):
    """
    Decorator that repeat calls a decorated function to get 
    all pages of WooCommerce API response.

    Combines the response data into a single list.

    Decorated function must accept parameters:
        - wcapi object
        - page number
    """
    def wrapper(wcapi, page=0, *args, **kwargs):
        items = []
        page = 0
        num_pages = WC_MAX_API_RESULT_COUNT

        while page < num_pages:
            page += 1
            log.debug(f"{page=}")

            response = func(wcapi, page=page, *args, **kwargs)

            items.extend(response.json())
            num_pages = int(response.headers["X-WP-TotalPages"])
            num_products = int(response.headers["X-WP-Total"])

        log.debug(f"{num_products=}, {len(items)=}")
        return items
    return wrapper


@wcapi_aggregate_paginated_response
def get_all_wc_orders(wcapi, page=1):
    """
    Query WooCommerce rest api for all products
    """
    response = wcapi.get(
        "orders",
        params={
            "per_page": WC_MAX_API_RESULT_COUNT,
            "page": page,
        },
    )
    response.raise_for_status()
    return response

orders = get_all_wc_orders(wcapi)

Upvotes: 0

gtopal
gtopal

Reputation: 594

First: Initialize your API (as you did).

wcapi = API(
        url=eshop.url,
        consumer_key=eshop.consumer_key,
        consumer_secret=eshop.consumer_secret,
        wp_api=True,
        version="wc/v2",
        query_string_auth=True,
        verify_ssl = True,
        timeout=10
    )

Second: Fetch the orders from your request(as you did).

 r=wcapi.get("orders")

Third: Fetch the total pages.

total_pages = int(r.headers['X-WP-TotalPages'])

Forth: For every page catch the json and access the data through the API.

for i in range(1,total_pages+1):
     r=wcapi.get("orders?&page="+str(i)).json()
     ...

Upvotes: 4

Demetris
Demetris

Reputation: 3241

The relevant parameters found in the corresponding documentation are page and per_page. The per_page parameter defines how many orders should be retrieved at every request. The page parameter defines the current page of the order collection.

For example, the request sent by wcapi.get('orders/per_page=5&page=2') will return orders 5 to 10.

However, as the default of per_page is 10, it is not clear as to why you get only 8 orders.

Upvotes: 0

Related Questions