TDKorn / my-magento

Python Magento 2 REST API Wrapper
https://my-magento.readthedocs.io
MIT License
11 stars 3 forks source link
api magento python wrapper

.. |.~.ACCESS_TOKEN| replace:: ACCESS_TOKEN .. _.~.ACCESS_TOKEN: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.ACCESS_TOKEN .. |.~.APIResponse| replace:: APIResponse .. .~.APIResponse: https://my-magento.readthedocs.io/en/latest/model.html#magento.models.model.APIResponse .. |.~.Category| replace:: Category .. .~.Category: https://my-magento.readthedocs.io/en/latest/category.html#magento.models.category.Category .. |.~.CategorySearch| replace:: CategorySearch .. _.~.CategorySearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.CategorySearch .. |.~.Client| replace:: Client .. .~.Client: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client .. |..Client.categories| replace:: Client.categories .. ..Client.categories: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.categories .. |..Client.customers| replace:: Client.customers .. ..Client.customers: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.customers .. |..Client.invoices| replace:: Client.invoices .. ..Client.invoices: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.invoices .. |..Client.order_items| replace:: Client.order_items .. _..Client.order_items: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.order_items .. |..Client.orders| replace:: Client.orders .. _..Client.orders: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.orders .. |..Client.product_attributes| replace:: Client.product_attributes .. _..Client.product_attributes: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.product_attributes .. |..Client.products| replace:: Client.products .. ..Client.products: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.products .. |..Client.scope| replace:: Client.scope .. ..Client.scope: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.scope .. |..Client.search| replace:: Client.search() .. _..Client.search: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.search .. |..Client.url_for| replace:: Client.url_for() .. _..Client.url_for: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.url_for .. |.~.Customer| replace:: Customer .. .~.Customer: https://my-magento.readthedocs.io/en/latest/customer.html#magento.models.customer.Customer .. |.~.CustomerSearch| replace:: CustomerSearch .. .~.CustomerSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.CustomerSearch .. |.~.Invoice| replace:: Invoice .. .~.Invoice: https://my-magento.readthedocs.io/en/latest/invoice.html#magento.models.invoice.Invoice .. |.~.InvoiceSearch| replace:: InvoiceSearch .. .~.InvoiceSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.InvoiceSearch .. |.~.MediaEntry| replace:: MediaEntry .. .~.MediaEntry: https://my-magento.readthedocs.io/en/latest/product.html#magento.models.product.MediaEntry .. |.~.Model| replace:: Model .. .~.Model: https://my-magento.readthedocs.io/en/latest/model.html#magento.models.model.Model .. |..Model.refresh| replace:: Model.refresh() .. ..Model.refresh: https://my-magento.readthedocs.io/en/latest/model.html#magento.models.model.Model.refresh .. |.~.Order| replace:: Order .. .~.Order: https://my-magento.readthedocs.io/en/latest/order.html#magento.models.order.Order .. |.~.OrderItem| replace:: OrderItem .. .~.OrderItem: https://my-magento.readthedocs.io/en/latest/order.html#magento.models.order.OrderItem .. |.~.OrderItemSearch| replace:: OrderItemSearch .. .~.OrderItemSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.OrderItemSearch .. |.~.OrderSearch| replace:: OrderSearch .. _.~.OrderSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.OrderSearch .. |.~.Product| replace:: Product .. .~.Product: https://my-magento.readthedocs.io/en/latest/product.html#magento.models.product.Product .. |.~.ProductAttribute| replace:: ProductAttribute .. .~.ProductAttribute: https://my-magento.readthedocs.io/en/latest/product.html#magento.models.product.ProductAttribute .. |.~.ProductAttributeSearch| replace:: ProductAttributeSearch .. _.~.ProductAttributeSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.ProductAttributeSearch .. |.~.ProductSearch| replace:: ProductSearch .. _.~.ProductSearch: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.ProductSearch .. |.~.ProductSearch.by_sku| replace:: by_sku() .. _.~.ProductSearch.by_sku: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.ProductSearch.by_sku .. |.~.SearchQuery| replace:: SearchQuery .. _.~.SearchQuery: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery .. |.~.SearchQuery.by_id| replace:: by_id() .. _.~.SearchQuery.by_id: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.by_id .. |.~.SearchQuery.by_list| replace:: by_list() .. _.~.SearchQuery.by_list: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.by_list .. |.~.SearchQuery.result| replace:: result .. _.~.SearchQuery.result: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.result .. |.~.USER_CREDENTIALS| replace:: USER_CREDENTIALS .. _.~.USER_CREDENTIALS: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.USER_CREDENTIALS .. |.~.add_criteria| replace:: add_criteria() .. _.~.add_criteria: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.add_criteria .. |.~.authenticate| replace:: authenticate() .. _.~.authenticate: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.authenticate .. |.~.by_id| replace:: by_id() .. _.~.by_id: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.by_id .. |.~.by_list| replace:: by_list() .. _.~.by_list: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.by_list .. |.~.delete| replace:: delete() .. .~.delete: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.delete .. |.~.execute| replace:: execute() .. .~.execute: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.execute .. |.~.get| replace:: get() .. _.~.get: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.get .. |..get_api| replace:: get_api() .. _..get_api: https://my-magento.readthedocs.io/en/latest/modules.html#magento.get_api .. |.~.get_api| replace:: get_api() .. _.~.get_api: https://my-magento.readthedocs.io/en/latest/modules.html#magento.get_api .. |.~.post| replace:: post() .. .~.post: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.post .. |.~.put| replace:: put() .. .~.put: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.put .. |.~.restrict_fields| replace:: restrict_fields() .. _.~.restrict_fields: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.restrict_fields .. |.~.scope| replace:: scope .. .~.scope: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.scope .. |.~.search| replace:: search() .. .~.search: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.search .. |.~.since| replace:: since() .. _.~.since: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.since .. |.~.until| replace:: until() .. _.~.until: https://my-magento.readthedocs.io/en/latest/search_module.html#magento.search.SearchQuery.until .. |.~.url_for| replace:: url_for() .. _.~.url_for: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Client.url_for .. |.~.views| replace:: views .. _.~.views: https://my-magento.readthedocs.io/en/latest/clients.html#magento.clients.Store.views

.. Title: MyMagento .. Description: A Python package that wraps and extends the Magento 2 REST API .. Author: TDKorn

.. meta:: :title: MyMagento :description: A Python package that wraps and extends the Magento 2 REST API

.. |RTD| replace:: Explore the docs ยป .. _RTD: https://my-magento.readthedocs.io/en/latest/ .. |api_endpoint| replace:: API endpoint .. _api_endpoint: https://adobe-commerce.redoc.ly/2.3.7-admin/

.. raw:: html

.. image:: https://raw.githubusercontent.com/TDKorn/my-magento/v2.2.0/docs/source/_static/magento_orange.png :alt: Logo for MyMagento: Python Magento 2 REST API Wrapper :width: 15% .. raw:: html

MyMagento๐Ÿ›’

A Python package that wraps and extends the Magento 2 REST API |RTD|_ .. image:: https://img.shields.io/pypi/v/my-magento?color=eb5202 :target: https://pypi.org/project/my-magento/ :alt: PyPI Version .. image:: https://img.shields.io/badge/GitHub-my--magento-4f1abc :target: https://github.com/tdkorn/my-magento :alt: GitHub Repository .. image:: https://static.pepy.tech/personalized-badge/my-magento?period=total&units=none&left_color=grey&right_color=blue&left_text=Downloads :target: https://pepy.tech/project/my-magento .. image:: https://readthedocs.org/projects/my-magento/badge/?version=latest :target: https://my-magento.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. raw:: html

|

About MyMagento


.. raw:: html

   <table>
       <tr align="left">
           <th>

๐Ÿ“ What's MyMagento?

.. raw:: html

   </th>
   <tr><td>

``MyMagento`` is a highly interconnected package that wraps and extends the Magento 2 REST API,
providing a more intuitive and user-friendly interface to access and update your store.

.. raw:: html

   </td></tr>
   </table>

MyMagento simplifies interaction with the Magento 2 REST API
============================================================

If you've worked with the Magento 2 API, you'll know that not all endpoints are created equally.

``MyMagento`` aims to streamline your workflow by simplifying a
variety of commonly needed API operations.

...

Main Components
==================================

.. raw:: html

   <table>
       <tr align="left">
           <th>

๐Ÿ’ป The |.~.Client|_

.. raw:: html

   </th>
   <tr><td>

* Handles all API interactions
* Supports multiple store views
* Provides access to all other package components

.. raw:: html

   </td></tr>
   </table>

.. raw:: html

   <table>
       <tr align="left">
           <th>

๐Ÿ” The |.~.SearchQuery|_ and Subclasses

.. raw:: html

   </th>
   <tr><td>

* |.~.execute|_ a search query on any endpoint
* Intuitive interface for `Building Custom Search Queries <https://my-magento.readthedocs.io/en/latest/interact-with-api.html#custom-queries>`_
* All predefined methods retrieve data using only 1-2 API requests

.. raw:: html

   </td></tr>
   </table>

.. raw:: html

   <table>
       <tr align="left">
           <th>

๐Ÿง  The |.~.Model|_ Subclasses

.. raw:: html

   </th>
   <tr><td>

* Wrap all API responses in the package
* Provide additional endpoint-specific methods to retrieve and update data

.. raw:: html

   </td></tr>
   </table>

...

Available Endpoints
======================

``MyMagento`` is compatible with every |api_endpoint|_

Endpoints are wrapped with a |.~.Model|_ and |.~.SearchQuery|_ subclass as follows:

.. csv-table::
   :header: "**Endpoint**", "**Client Shortcut**", "|.~.SearchQuery|_ **Subclass**", "|.~.Model|_ **Subclass**"

   "``orders``", "|..Client.orders|_", "|.~.OrderSearch|_", "|.~.Order|_"
   "``orders/items``", "|..Client.order_items|_", "|.~.OrderItemSearch|_", "|.~.OrderItem|_"
   "``invoices``", "|..Client.invoices|_", "|.~.InvoiceSearch|_", "|.~.Invoice|_"
   "``products``", "|..Client.products|_", "|.~.ProductSearch|_", "|.~.Product|_"
   "``products/attributes``", "|..Client.product_attributes|_", "|.~.ProductAttributeSearch|_", "|.~.ProductAttribute|_"
   "``categories``", "|..Client.categories|_", "|.~.CategorySearch|_", "|.~.Category|_"
   "``customers``", "|..Client.customers|_", "|.~.CustomerSearch|_", "|.~.Customer|_"
   "``endpoint``", "``Client.search('endpoint')``", "|.~.SearchQuery|_", "|.~.APIResponse|_"

...

โš™ Installing MyMagento

To install using pip::

pip install my-magento

Please note that MyMagento requires Python >= 3.10

...

๐Ÿ“š Documentation


Full documentation can be found on `ReadTheDocs <https://my-magento.readthedocs.io/en/latest/>`_

|

QuickStart: Login with MyMagento

MyMagento uses the |.~.Client|_ class to handle all interactions with the API.

.. raw:: html

๐Ÿ’ก Tip .. raw:: html
See `Get a Magento 2 REST API Token With MyMagento `_ for full details on generating an access token .. raw:: html

Setting the Login Credentials

To generate an |.~.ACCESSTOKEN| you'll need to |.~.authenticate|_ your |.~.USERCREDENTIALS|.

Creating a |.~.Client|_ requires a domain, username, and password at minimum.

.. code-block:: python

domain = 'website.com' username ='username' password = 'password'

If you're using a local installation of Magento you'll need to set local=True. Your domain should look like this:

.. code-block:: python

domain = '127.0.0.1/path/to/magento'

...

Getting a |.~.Client|_

Option 1: Initialize a |.~.Client|_ Directly ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  from magento import Client

  >>> api = Client(domain, username, password, **kwargs)

Option 2: Call |.~.getapi| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python

  import magento

  >>> api = magento.get_api(**kwargs)

|..getapi| takes the same keyword arguments as the |.~.Client|_

.. code-block:: python

import os

os.environ['MAGENTO_DOMAIN'] = domain os.environ['MAGENTO_USERNAME']= username os.environ['MAGENTO_PASSWORD']= password

...

Getting an |.~.ACCESSTOKEN|

Unless you specify login=False, the |.~.Client| will automatically call |.~.authenticate| once initialized:

.. code-block:: python

api.authenticate()

|[ MyMagento | website_username ]|: Authenticating username on website.com... |[ MyMagento | website_username ]|: Logged in to username

|

Performing a |.~.search|_


.. |api_endpoints| replace:: API endpoint
.. _api_endpoints: https://adobe-commerce.redoc.ly/2.3.7-admin/

The |..Client.search|_ method lets you |.~.execute|_ a query on
any |api_endpoints|_

It creates a |.~.SearchQuery|_ for the endpoint,
allowing you to retrieve data about

* An individual item (ex. |.~.SearchQuery.by_id|_)
* A list of items (ex. |.~.SearchQuery.by_list|_)
* Any search criteria you desire (see `Building Custom Search Queries <https://my-magento.readthedocs.io/en/latest/interact-with-api.html#custom-queries>`_)

...

Example: |.~.search|_ an endpoint |.~.by_id|_
=====================================================

.. code-block:: python

    # Query the "invoices" endpoint (also: api.invoices)
    >>> api.search("invoices").by_id(1)

    <Magento Invoice: "#000000001"> for <Magento Order: "#000000001" placed on 2022-11-01 03:27:33>

Example: |.~.search|_ an endpoint |.~.by_list|_
=======================================================

.. code-block:: python

    # Retrieve invoices from a list of invoice ids
    >>> ids = list(range(1,101))
    >>> api.invoices.by_list("entity_id", ids)

    [<Magento Invoice: "#000000001"> for <Magento Order: "#000000001" placed on 2022-11-01 03:27:33>, ...]

...

Search Results: The |.~.Model|_ Classes

.. |the_models| replace:: the magento.models subpackage .. _the_models: models.html

The |.~.SearchQuery.result| of any |.~.SearchQuery| will be parsed and wrapped by a |.~.Model|_ class in |themodels|.

These classes make the API response data easier to work with.

They also provide endpoint-specific methods to update store data and search for related items.

Example: Retrieving every |.~.Order| containing a |.~.Product|

Let's retrieve a |.~.Product|_ using |.~.ProductSearch.bysku|

.. code-block:: python

product = api.products.by_sku("24-MB01")

We can search for orders containing this product in multiple ways:

.. code-block:: python

# Using the Product itself
>>> product.get_orders()

[<Magento Order: "#000000003" placed on 2022-12-21 08:09:33>, ... ]

# Using an OrderSearch
>>> api.orders.by_product(product)
>>> api.orders.by_product_id(product.id)
>>> api.orders.by_sku(product.sku)

[<Magento Order: "#000000003" placed on 2022-12-21 08:09:33>, ... ]

Example: Retrieving all |.~.Product|\s and |.~.Invoice|\s for a |.~.Category|_

.. code-block:: python

>>> category = api.categories.by_name("Watches")
>>> category.get_products()
>>> category.get_invoices()

[<Magento Product: 24-MG04>, <Magento Product: 24-MG01>, <Magento Product: 24-MG03>, ... ]
[<Magento Invoice: "#000000004"> for <Magento Order: "#000000004" placed on 2022-11-14 03:27:33>, ... ]

Example: Updating the Thumbnail |.~.MediaEntry| of a |.~.Product|

.. code-block:: python

# Update product thumbnail label on specific store view

product.thumbnail.set_alt_text("bonjour", scope="FR") print(product.thumbnail)

<MediaEntry 3417 for <Magento Product: 24-MB01>: bonjour>

...

.. raw:: html

๐Ÿ’ก Tip: Set the Store Scope .. raw:: html
If you have multiple store views, a ``store_code`` can be specified when retrieving/updating data * The |..Client.scope|_ is used by default - simply change it to switch store |.~.views|_ * Passing the ``scope`` keyword argument to |..Client.url_for|_, |..Model.refresh|_, and some Model update methods will temporarily override the Client scope .. raw:: html

...

.. _Custom Queries:

Building Custom Search Queries


In addition to the predefined methods, you can also build your own queries

* Simply |.~.add_criteria|_, |.~.restrict_fields|_, and |.~.execute|_ the search
* The |.~.since|_ and |.~.until|_ methods allow you to further filter your query by date

.. raw:: html

   <table>
       <tr align="left">
           <th>

๐Ÿ“‹ Example: Retrieve Orders Over $50 Placed Since the Start of 2023

.. raw:: html

   </th>
   <tr><td>

.. code-block:: python

 >>> api.orders.add_criteria(
 ...    field="grand_total",
 ...    value="50",
 ...    condition="gt"
 ... ).since("2023-01-01").execute()

 [<Magento Order: "#000000012" placed on 2023-01-02 05:19:55>, ...]

.. raw:: html

   </td></tr>
   </table>

...

Making Authorized Requests

The |.~.Client|_ can be used to generate the |.~.urlfor| any API endpoint, including a store |.~.scope|_.

You can use this URL to make an authorized |.~.get|, |.~.post|, |.~.put|, or |.~.delete| request.

Example: Making a |.~.get|_ Request

.. code-block:: python

Request the data for credit memo with id 7

url = api.url_for('creditmemo/7') response = api.get(url) print(response.json())

{'adjustment': 1.5, 'adjustment_negative': 0, 'adjustment_positive': 1.5, 'base_adjustment': 1.5, ... }

.. raw:: html

๐Ÿ“ Note .. raw:: html
A |.~.search|_ is simpler than making |.~.get|_ requests, as the result will be wrapped by |.~.APIResponse|_ or other |.~.Model|_ .. code-block:: python # Retrieve credit memo with id 7 using a search >>> memo = api.search("creditmemo").by_id(7) >>> print(memo.data) >>> print(memo) {'adjustment': 1.5, 'adjustment_negative': 0, 'adjustment_positive': 1.5, 'base_adjustment': 1.5, ... } .. raw:: html