Export/Import Guide¶
Overview¶
strapi-kit provides comprehensive export/import functionality for migrating Strapi content between instances. The system automatically handles relation resolution using content type schemas.
Quick Start¶
Export¶
from strapi_kit import SyncClient, StrapiExporter, StrapiConfig
config = StrapiConfig(base_url="http://localhost:1337", api_token="token")
with SyncClient(config) as client:
exporter = StrapiExporter(client)
# Export content types
export_data = exporter.export_content_types([
"api::article.article",
"api::author.author"
])
# Save to file
exporter.save_to_file(export_data, "export.json")
Import¶
from strapi_kit import StrapiImporter
target_config = StrapiConfig(base_url="http://localhost:1338", api_token="token")
with SyncClient(target_config) as client:
importer = StrapiImporter(client)
# Load and import
export_data = StrapiExporter.load_from_file("export.json")
result = importer.import_data(export_data)
print(f"Imported {result.entities_imported} entities")
Relation Resolution¶
How It Works¶
Relations are automatically resolved using content type schemas:
- During Export: Schemas are fetched from the Content-Type Builder API
- Schema Storage: Schemas are included in the export metadata
- During Import: Relations are resolved by looking up target content types from schemas
Example: When importing an article with {"author": [5]}, the system:
1. Looks up the schema to find that author targets "api::author.author"
2. Uses the ID mapping to convert old ID 5 to the new ID in the target instance
3. Updates the article with the resolved relation
Schema Structure¶
Schemas include field metadata for relation resolution:
{
"uid": "api::article.article",
"fields": {
"author": {
"type": "relation",
"relation": "manyToOne",
"target": "api::author.author" # Used for ID mapping
}
}
}
Export Options¶
Basic Export¶
Schemas are always included for relation resolution.
Export with Media¶
export_data = exporter.export_content_types(
["api::article.article"],
include_media=True,
media_dir="export/media"
)
Progress Tracking¶
def progress_callback(current, total, message):
print(f"[{current}/{total}] {message}")
export_data = exporter.export_content_types(
["api::article.article"],
progress_callback=progress_callback
)
Import Options¶
Basic Import¶
Import Options¶
from strapi_kit.models import ImportOptions, ConflictResolution
options = ImportOptions(
skip_relations=False, # Import relations (default)
import_media=True, # Import media files
conflict_resolution=ConflictResolution.SKIP, # Skip conflicts
dry_run=False # Actually perform import
)
result = importer.import_data(export_data, options)
Conflict Resolution Strategies¶
SKIP: Skip entities that already existUPDATE: Update existing entities (not yet implemented)ERROR: Raise error on conflicts
Working with Relations¶
Ensuring Complete Exports¶
To ensure all relations are resolved, include all related content types:
# Include all related content types
export_data = exporter.export_content_types([
"api::article.article",
"api::author.author", # Referenced by articles
"api::category.category" # Referenced by articles
])
Checking Import Results¶
result = importer.import_data(export_data)
# Check results
print(f"Success: {result.success}")
print(f"Entities imported: {result.entities_imported}")
print(f"Entities skipped: {result.entities_skipped}")
# View ID mapping
for content_type, mapping in result.id_mapping.items():
print(f"{content_type}:")
for old_id, new_id in mapping.items():
print(f" {old_id} -> {new_id}")
# Check for warnings/errors
for warning in result.warnings:
print(f"Warning: {warning}")
for error in result.errors:
print(f"Error: {error}")
Inspecting Schemas¶
You can inspect schemas in export data:
# Load export
export_data = StrapiExporter.load_from_file("export.json")
# Inspect schemas
for content_type, schema in export_data.metadata.schemas.items():
print(f"\n{content_type}:")
print(f" Display Name: {schema.display_name}")
# Show relations
for field_name, field in schema.fields.items():
if field.type == "relation":
print(f" Relation: {field_name} -> {field.target}")
Direct Schema Cache Usage¶
The schema cache can be used directly:
from strapi_kit.cache import InMemorySchemaCache
with SyncClient(config) as client:
cache = InMemorySchemaCache(client)
# Get schema
schema = cache.get_schema("api::article.article")
# Check relation targets
target = schema.get_field_target("author")
print(target) # "api::author.author"
# Check if field is a relation
is_rel = schema.is_relation_field("author")
print(is_rel) # True
Troubleshooting¶
Missing Relations¶
Issue: "No ID mapping for X" warning
Cause: A relation references a content type not included in the export
Solution: Include all related content types:
export_data = exporter.export_content_types([
"api::article.article",
"api::author.author", # Add missing content types
])
Unresolved IDs¶
Issue: "Could not resolve X ID Y for field Z" warning
Cause: A specific entity referenced by a relation wasn't included
Solutions: 1. Ensure all entities are exported (check filters) 2. Import the missing entities first 3. Create the missing entities manually in target instance
Schema Fetch Failures¶
Issue: "Failed to fetch schema for X" error
Cause: Content-Type Builder API unavailable or content type doesn't exist
Solutions: 1. Verify content type UID is correct 2. Check API token has permissions to access Content-Type Builder 3. Verify Strapi instance is accessible
Performance Considerations¶
- Export: +1 API call per content type (schema fetch)
- Import: No additional API calls (schemas loaded from export)
- Memory: ~10KB per content type schema (typical)
- Cache: In-memory only, cleared after operation
Best Practices¶
- Export Complete Sets: Always export related content types together
- Test First: Use
dry_run=Trueto validate imports - Check Results: Always review warnings and errors after import
- Media Handling: Download media files if needed for offline migration
- Version Compatibility: Ensure source and target Strapi versions are compatible
Schema Model Reference¶
from strapi_kit.models import (
ContentTypeSchema,
FieldSchema,
FieldType,
RelationType
)
# ContentTypeSchema
schema = ContentTypeSchema(
uid="api::article.article",
display_name="Article",
kind="collectionType",
fields={...}
)
# Helper methods
target = schema.get_field_target("author")
is_rel = schema.is_relation_field("author")
Example: Complete Migration¶
from strapi_kit import SyncClient, StrapiConfig, StrapiExporter, StrapiImporter
from strapi_kit.models import ImportOptions
# Source instance
source_config = StrapiConfig(
base_url="http://localhost:1337",
api_token="source-token"
)
# Target instance
target_config = StrapiConfig(
base_url="http://localhost:1338",
api_token="target-token"
)
# Export from source
with SyncClient(source_config) as client:
exporter = StrapiExporter(client)
export_data = exporter.export_content_types([
"api::article.article",
"api::author.author",
"api::category.category"
])
exporter.save_to_file(export_data, "migration.json")
# Import to target
with SyncClient(target_config) as client:
importer = StrapiImporter(client)
export_data = StrapiExporter.load_from_file("migration.json")
# Dry run first
result = importer.import_data(
export_data,
options=ImportOptions(dry_run=True)
)
if result.success:
# Actual import
result = importer.import_data(export_data)
print(f"Migration complete: {result.entities_imported} entities")