Skip to main content

Python port of @drupal-api-client/api-client — base HTTP client for Drupal APIs

Project description

drupal-api-client

A Python client for Drupal APIs — a port of @drupal-api-client/api-client (JavaScript).

CI PyPI

What's included

  • ApiClient — base HTTP client with auth, caching, logging, and serializer hooks.
  • DecoupledRouterClient — resolves Drupal path aliases via the Decoupled Router module.
  • JsonApiClient — full CRUD over Drupal's JSON:API module.

Installation

pip install drupal-api-client

For building query strings, install the companion package:

pip install drupal-jsonapi-params

Quick start

Reading a collection

from drupal_api_client import JsonApiClient

with JsonApiClient("https://example.com") as client:
    articles = client.get_collection("node--article")
    for article in articles["data"]:
        print(article["attributes"]["title"])

Reading with filters (using drupal-jsonapi-params)

from drupal_api_client import JsonApiClient
from drupal_jsonapi_params import DrupalJsonApiParams, FilterOperator

params = (
    DrupalJsonApiParams()
    .add_filter("status", "1")
    .add_filter("title", "Hello", FilterOperator.CONTAINS)
    .add_include(["field_image"])
    .add_page_limit(10)
)

with JsonApiClient("https://example.com") as client:
    articles = client.get_collection("node--article", query_string=params)

Resolving a path alias

from drupal_api_client import JsonApiClient

with JsonApiClient("https://example.com") as client:
    article = client.get_resource_by_path("/about-us")
    print(article["data"]["attributes"]["title"])

Authenticated writes

from drupal_api_client import JsonApiClient, BasicAuth

auth = BasicAuth(username="admin", password="secret")
with JsonApiClient("https://example.com", authentication=auth) as client:
    new_article = client.create_resource(
        "node--article",
        {
            "data": {
                "type": "node--article",
                "attributes": {"title": "New article", "body": {"value": "..."}},
            }
        },
    )

    client.update_resource(
        "node--article",
        new_article["data"]["id"],
        {"data": {"type": "node--article", "id": new_article["data"]["id"], "attributes": {"title": "Updated"}}},
    )

    client.delete_resource("node--article", new_article["data"]["id"])

Authentication

Three auth types are supported:

from drupal_api_client import BasicAuth, OAuthAuth, CustomAuth

# HTTP Basic
BasicAuth(username="admin", password="secret")

# OAuth2 (client_credentials or password grant)
OAuthAuth(client_id="...", client_secret="...")
OAuthAuth(client_id="...", client_secret="...", grant_type="password",
          username="...", password="...")

# Custom (passed verbatim into the Authorization header)
CustomAuth(value="Bearer my-token-here")

Caching

Pass any object implementing the Cache protocol (get, set, delete):

from drupal_api_client import JsonApiClient, InMemoryCache

with JsonApiClient("https://example.com", cache=InMemoryCache()) as client:
    client.get_resource("node--article", "abc-123")  # HTTP call
    client.get_resource("node--article", "abc-123")  # cache hit, no HTTP

Write methods invalidate the canonical cached entries for the affected resource. Cache entries with locales or query strings are not auto-invalidated — pass disable_cache=True to bypass them, or implement a custom cache with prefix-based invalidation.

Discriminated unions

get_resource_by_path raises ResourceNotFoundError when the path can't be resolved. For lower-level access, DecoupledRouterClient.translate_path returns a discriminated union:

from drupal_api_client import DecoupledRouterClient, ResolvedPath, UnresolvedPath

with DecoupledRouterClient("https://example.com") as router:
    result = router.translate_path("/about-us")
    match result:
        case ResolvedPath(entity=entity, label=label):
            print(f"Found {label}: {entity['uuid']}")
        case UnresolvedPath(message=msg):
            print(f"Not found: {msg}")

What's not in v0.2.0

  • GraphQL client — coming in v0.3.0.
  • Async support — sync only for now. Use asyncio.to_thread() to call from async code.
  • Built-in JSON:API document parser — responses are returned as parsed dicts. Use jsonapi-client or write your own parser if you need flattened resources with resolved relationships.

Logging

Configure standard Python logging:

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("drupal_api_client").setLevel(logging.DEBUG)

Compatibility

  • Python 3.10+
  • Drupal 9.x, 10.x, 11.x with the JSON:API module enabled
  • Optional Drupal modules: Decoupled Router (for path resolution), JSON:API Views (for get_view)

License

ISC. See LICENSE. Original JavaScript implementation is MIT-licensed by the Drupal API Client contributors; see NOTICE.

Contributing

Issues and pull requests welcome at github.com/VincenzoGambino/drupal-api-client-python.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drupal_api_client-0.2.0.tar.gz (21.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drupal_api_client-0.2.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file drupal_api_client-0.2.0.tar.gz.

File metadata

  • Download URL: drupal_api_client-0.2.0.tar.gz
  • Upload date:
  • Size: 21.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for drupal_api_client-0.2.0.tar.gz
Algorithm Hash digest
SHA256 96380db2341caaefbfe829c4a6eb5dadae5068cb26f98d9130a2e9e42a5cda11
MD5 764696b0f287cf789e39e3111467f876
BLAKE2b-256 106e25be7678f443cc67088797e86370235fd21669827218f8711208a363f352

See more details on using hashes here.

Provenance

The following attestation bundles were made for drupal_api_client-0.2.0.tar.gz:

Publisher: publish.yml on VincenzoGambino/drupal-api-client-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file drupal_api_client-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for drupal_api_client-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 32902c09bc4fc9d19ae2e2b668b0705c29de54ad1db1b8cd5ef454ca75db87a1
MD5 f7e0e189f5572f4a12c53c405be80aef
BLAKE2b-256 575f5aefadae7e20eca883fa7bbb323714c919befcd1f3fc4e40ca6963f5dad2

See more details on using hashes here.

Provenance

The following attestation bundles were made for drupal_api_client-0.2.0-py3-none-any.whl:

Publisher: publish.yml on VincenzoGambino/drupal-api-client-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page