Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A Python library to easily interface with Strapi from your Python project.

License

Notifications You must be signed in to change notification settings

Akinwalee/strapi-python

Repository files navigation

Strapi Python Client

PyPI version Python License: MIT

The unofficial Python client library to easily interface with Strapi from your Python project.

Installation

pip install strapi-py

Quick Start

from strapi_client import strapi
# Create a client instance
client = strapi(base_url="http://localhost:1337/api")
# Fetch data from a custom endpoint
response = client.fetch('/articles')
data = response.json()
print(data)

Authentication

API Token Authentication

from strapi_client import strapi
# Initialize the client with yor API token
client = strapi(
 base_url="http://localhost:1337/api",
 auth="your-api-token-here"
)
# All requests will include the Authorization header
response = client.fetch('/articles')

Custom Headers

client = strapi(
 base_url="http://localhost:1337/api",
 headers={
 "X-Custom-Header": "value",
 "Accept-Language": "en"
 }
)

Working with Collection Types

Collection types represent multiple entries (e.g., articles, products, users).

Find All Entries

# Get all articles
articles = client.collection('articles')
response = articles.find()
print(response.json())

Find with Filters and Sorting

articles = client.collection('articles')
# Filter and sort
response = articles.find(params={
 'filters': {
 'title': {
 '$contains': 'Python'
 },
 'publishedAt': {
 '$notNull': True
 }
 },
 'sort': ['createdAt:desc'],
 'pagination': {
 'page': 1,
 'pageSize': 10
 },
 'populate': '*'
})

Find One Entry

articles = client.collection('articles')
# Get article with documentId j964065dnjrdr4u89weh79xl
response = articles.find_one("j964065dnjrdr4u89weh79xl", params={
 'populate': ['author', 'comments']
})
print(response.json())

NOTE

Strapi 5 replaces the numeric id used in Strapi 4 with a new 24-character alphanumeric identifier called documentId. When working with Strapi 5, use documentId as the primary resource identifier. This library continues to support the legacy id field for Strapi 4 projects.

Create an Entry

articles = client.collection('articles')
response = articles.create(data={
 'title': 'My New Article',
 'content': 'This is the article content',
 'publishedAt': '2024-01-01T00:00:00.000Z'
})
created_article = response.json()
print(f"Created article with ID: {created_article['data']['documentId']}")

Update an Entry

articles = client.collection('articles')
response = articles.update(1, data={
 'title': 'Updated Article Title',
 'content': 'Updated content'
})

Delete an Entry

articles = client.collection('articles')
response = articles.delete(1)

Working with Single Types

Single types represent a single entry (e.g., homepage, about page, settings).

Find Single Type

homepage = client.single('homepage')
response = homepage.find(params={'populate': '*'})
print(response.json())

Update Single Type

homepage = client.single('homepage')
response = homepage.update(data={
 'title': 'Welcome to My Site',
 'description': 'A brief description'
})

Delete Single Type

homepage = client.single('homepage')
response = homepage.delete()

Working with Plugins

Users & Permissions Plugin

# Access users endpoint
users = client.collection(
 resource='users',
 plugin={'name': 'users-permissions', 'prefix': ''}
)
# Create a new user
response = users.create(data={
 'username': 'johndoe',
 'email': 'john@example.com',
 'password': 'SecurePassword123!'
})

Custom Plugin with Prefix

# Access a custom plugin endpoint
blog_posts = client.collection(
 resource='posts',
 plugin={'name': 'blog', 'prefix': 'blog'}
)
# This will make requests to /blog/posts
response = blog_posts.find()

Custom Plugin without Prefix

# Disable plugin prefix
custom_content = client.collection(
 resource='items',
 plugin={'name': 'custom-plugin', 'prefix': ''}
)
# This will make requests to /items

File Management

Upload a File

# Upload from bytes
with open('image.jpg', 'rb') as f:
 file_data = f.read()
response = client.files.upload(
 file_data=file_data,
 filename='image.jpg',
 mimetype='image/jpeg',
 file_info={
 'alternativeText': 'A sample image',
 'caption': 'My caption'
 }
)
print(response.json())

Upload with File Object

import io
# Upload from file-like object
with open('document.pdf', 'rb') as f:
 response = client.files.upload(
 file_data=f,
 filename='document.pdf',
 mimetype='application/pdf'
 )

List All Files

# Get all files
response = client.files.find()
files = response.json()
# Filter files
response = client.files.find(params={
 'filters': {
 'mime': {'$contains': 'image'}
 },
 'sort': 'createdAt:desc'
})

Get a Specific File

response = client.files.find_one(file_id="clkgylmcc000008lcdd868feh")
file_data = response.json()
print(f"File URL: {file_data['url']}")

Update File Metadata

response = client.files.update(
 file_id="clkgylmcc000008lcdd868feh",
 file_info={
 'name': 'renamed-file.jpg',
 'alternativeText': 'Updated alt text',
 'caption': 'Updated caption'
 }
)

Delete a File

response = client.files.delete(file_id="clkgylmcc000008lcdd868feh")

Custom Paths

You can specify custom API paths for content types:

# Use a custom path instead of the default /articles
custom_articles = client.collection(
 resource='articles',
 path='/v2/custom-articles'
)
response = custom_articles.find()
# Makes request to /v2/custom-articles

Error Handling

The library provides detailed error messages from Strapi, making debugging much easier. When an error occurs, you'll see:

  • Error type/name (e.g., ValidationError, ApplicationError)
  • Clear error message from Strapi
  • Detailed field-level validation errors with paths
  • Access to the original response for debugging

Basic Error Handling

from strapi_client import (
 strapi,
 StrapiHTTPError,
 StrapiHTTPNotFoundError,
 StrapiHTTPUnauthorizedError,
 StrapiHTTPBadRequestError,
 StrapiValidationError
)
try:
 client = strapi(base_url="http://localhost:1337/api")
 articles = client.collection('articles')
 response = articles.find_one(999)
except StrapiHTTPNotFoundError as e:
 print(f"Article not found: {e}")
 print(f"Status code: {e.response.status_code}")
except StrapiHTTPUnauthorizedError as e:
 print(f"Authentication failed: {e}")
except StrapiHTTPBadRequestError as e:
 print(f"Bad request: {e}")
 print(f"Full error: {e.response.json()}")
except StrapiHTTPError as e:
 print(f"HTTP error occurred: {e}")
 print(f"Response: {e.response.text}")
except StrapiValidationError as e:
 print(f"Validation error: {e}")

Detailed Validation Errors

When you have validation errors (e.g., in dynamic zones or complex fields), the error message will show exactly which fields are problematic:

try:
 blog = client.collection('blogs')
 response = blog.create(data={
 'title': '', # Invalid: too short
 'blocks': [
 {
 # Missing __component field
 'body': 'Some content'
 }
 ]
 })
except StrapiHTTPBadRequestError as e:
 print(e)
 # Output:
 # Strapi API Error (400): [ValidationError] Invalid data provided
 # Validation errors:
 # - title: title must be at least 1 characters
 # - blocks.0.__component: component is required

Accessing Response Details

All HTTP errors preserve the original response, allowing you to access additional details:

try:
 response = client.collection('articles').create(data={...})
except StrapiHTTPBadRequestError as e:
 # Get status code
 print(f"Status: {e.response.status_code}")
 
 # Get full error details
 error_details = e.response.json()
 print(f"Error name: {error_details['error']['name']}")
 print(f"Error details: {error_details['error']['details']}")
 
 # Get request Url
 print(f"Request URL: {e.response.request.url}")

Available Error Types

  • StrapiError - Base error class
  • StrapiValidationError - Invalid input or configuration
  • StrapiHTTPError - Base HTTP error (non-2xx responses)
  • StrapiHTTPBadRequestError - 400 Bad Request (validation errors, malformed requests)
  • StrapiHTTPUnauthorizedError - 401 Unauthorized (authentication required)
  • StrapiHTTPForbiddenError - 403 Forbidden (insufficient permissions)
  • StrapiHTTPNotFoundError - 404 Not Found (resource doesn't exist)
  • StrapiHTTPTimeoutError - 408 Request Timeout
  • StrapiHTTPInternalServerError - 500 Internal Server Error

Advanced Usage

Locale Support

articles = client.collection('articles')
# Fetch French content
response = articles.find(params={'locale': 'fr'})
# Fetch specific entry in Spanish
response = articles.find_one(1, params={'locale': 'es'})

Population

articles = client.collection('articles')
# Populate all relations
response = articles.find(params={'populate': '*'})
# Populate specific relations
response = articles.find(params={
 'populate': ['author', 'categories', 'cover']
})
# Deep population
response = articles.find(params={
 'populate': {
 'author': {
 'populate': ['avatar']
 },
 'categories': '*'
 }
})

Field Selection

articles = client.collection('articles')
# Select specific fields only
response = articles.find(params={
 'fields': ['title', 'description', 'publishedAt']
})

Requirements

  • Python >= 3.10
  • httpx >= 0.27.0

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Links

About

A Python library to easily interface with Strapi from your Python project.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /