Hi, thanks for this. Had to make a few tweaks but it worked out well and am happy I found it! ๐ช
I also added pagination for orders. Really I'd just use Shopify API client (if there is one) but I haven't programmed Python in 15 or so years so figured I'd add it for fun. (Still don't get what the fuss is about: re.match
vs re.search
, still no private methods, different calling syntax between class instance variables and methods ๐๐คฏ). Here's the diff if you're interested:
diff --git a/apps/orders/management/commands/sync_shopify_orders.py b/apps/orders/management/commands/sync_shopify_orders.py
index a7ef0ea..e184e1c 100644
--- a/apps/orders/management/commands/sync_shopify_orders.py
+++ b/apps/orders/management/commands/sync_shopify_orders.py
@@ -1,4 +1,6 @@
"""Sync Orders"""
+import re
+
from django.core.management import BaseCommand
from utils.shopify_utils import ShopifyOrderFetch
from apps.orders.managers.order_manager import OrderManager
@@ -6,16 +8,44 @@ from apps.orders.managers.order_manager import OrderManager
class Command(BaseCommand):
"""Command to fetch shopify Orders one time."""
+ PAGE_INFO = re.compile(r'page_info=(\w+)>;\s+rel="(\w+)"')
+
def __init__(self, *args, **kwargs):
"""init method where all the managers are initialized for the command."""
super(Command, self).__init__(*args, **kwargs)
self.order_manager = OrderManager()
-
+
+ def _page_info(self, link):
+ pages = {}
+
+ if not link:
+ return pages
+
+ for part in link.split(",", 2):
+ match = self.PAGE_INFO.search(part)
+ if match:
+ pages[match[2]] = match[1]
+
+ return pages
+
def handle(self, *args, **options):
"""handling the command begins here."""
- all_orders = ShopifyOrderFetch().fetch_all_orders()
- orders = all_orders['orders']
- for order in orders:
- self.order_manager.parse_and_create_order(order)
-
+
+ next_page = None
+
+ while True:
+ response = ShopifyOrderFetch().fetch_all_orders(next_page)
+ if response.status_code != 200:
+ raise Exception("Failed to retrieve orders: %s " % response.text)
+
+ orders = (response.json())["orders"]
+
+ for order in orders:
+ self.order_manager.parse_and_create_order(order)
+
+ pages = self._page_info(response.headers["Link"])
+ next_page = pages.get('next')
+
+ if not next_page:
+ break
diff --git a/utils/shopify_utils.py b/utils/shopify_utils.py
index b163df7..2a1fce8 100644
--- a/utils/shopify_utils.py
+++ b/utils/shopify_utils.py
@@ -50,15 +50,15 @@ class ShopifyProductFetch(ShopifyBaseRequest):
def fetch_single_product(self, shopify_product_id):
url = "{}{}".format(self.base_url, SHOPIFY_SINGLE_PRODUCT_DATA_SUFFIX)
url = url.format(product_id=shopify_product_id)
-
+
response = self.make_request("GET", url)
- return response.json()
+ return response
def fetch_single_variant(self, shopify_variant_id):
url = "{}{}".format(self.base_url, SHOPIFY_SINGLE_VARIANT_SUFFIX)
url = url.format(variant_id=shopify_variant_id)
-
+
response = self.make_request("GET", url)
return response.json()
@@ -81,22 +81,22 @@ class ShopifyOrderFetch(ShopifyBaseRequest):
def fetch_single_customer(self, shopify_customer_id):
url = "{}{}".format(self.base_url, SHOPIFY_SINGLE_CUSTOMER_SUFFIX)
url = url.format(customer_id=shopify_customer_id)
-
+
response = self.make_request("GET", url)
return response.json()
- def fetch_all_orders(self):
+ def fetch_all_orders(self, page = None):
url = "{}{}".format(self.base_url, SHOPIFY_ALL_ORDERS_SUFFIX)
+ if page:
+ url += "?page_info=%s" % page
- response = self.make_request("GET", url)
-
- return response.json()
+ return self.make_request("GET", url)
def fetch_single_order(self, shopify_order_id):
url = "{}{}".format(self.base_url, SHOPIFY_SINGLE_order_SUFFIX)
url = url.format(order_id=shopify_order_id)
-
+
response = self.make_request("GET", url)
return response.json()