PyArchInit Import/Export - Complete Guide with Automatic Backup

Date:

2025-10-28

Version:

1.7.0+

Status:

✅ Complete and Tested System

Quick Answer

YES! When you import a PyArchInit database (SQLite or PostgreSQL) through:

The system automatically:

  1. Creates a backup of the original database

  2. Adds missing i18n columns (if needed)

  3. Imports all data (Sites, US, Relationships, etc.)

Overview

The PyArchInit Import/Export system provides bidirectional synchronization between PyArchInit and PyArchInit-Mini databases. This powerful feature allows you to:

  • Migrate existing PyArchInit projects to PyArchInit-Mini

  • Keep databases synchronized across multiple installations

  • Create backups before any database modifications

  • Add internationalization (i18n) support automatically

  • Filter imports by specific archaeological sites

The system supports both SQLite and PostgreSQL databases and includes automatic safety features to protect your data.

Automatic Backup System

How It Works

Before modifying the source database, the system automatically creates a timestamped backup:

from pyarchinit_mini.services.import_export_service import ImportExportService

# Initialize the service with database connections
service = ImportExportService(
    mini_db_connection='sqlite:///pyarchinit_mini.db',
    source_db_connection='sqlite:///my_pyarchinit.db'
)

# Backup is created BEFORE any modifications
stats = service.import_us(sito_filter=['Site1'])

# Backup path is included in the statistics
print(f"Backup created: {stats.get('backup_path')}")
# Output: Backup created: /path/to/my_pyarchinit.db.backup_20251028_143025

Backup Format

SQLite Backup:

Original database: /path/to/pyarchinit.db
Backup created:    /path/to/pyarchinit.db.backup_20251028_143025
                                        ^^^^^^^^^^^^^^^^
                                        YYYYMMDD_HHMMSS (timestamp)

PostgreSQL Backup:

Original database: my_database (PostgreSQL)
Backup created:    my_database_backup_20251028_143025.sql
                               ^^^^^^^^^^^^^^^^
                               YYYYMMDD_HHMMSS (timestamp)

Backup Features

  1. Automatic: Created before every modification

  2. Safe: Backup happens BEFORE any ALTER TABLE operations

  3. Timestamped: Unique name with date/time

  4. Once per session: Multiple imports reuse the same backup

  5. Optional: Can be disabled with auto_backup=False

  6. Verifiable: Path returned in import statistics

Complete Import Workflows

2. Desktop GUI

Launch:

python desktop_gui/main.py
# Or: pyarchinit-mini-gui

Steps:

  1. Menu: File → Import from PyArchInit

  2. Select database:

    • SQLite: Browse for the .db file

    • PostgreSQL: Form with credentials

  3. Select entities to import:

    • Sites

    • US + Relationships

    • Inventario

    • Periodizzazione

  4. Click Import

Backup: Created automatically the same way as Web GUI

3. CLI (Command Line / Python Script)

Complete Example

#!/usr/bin/env python3
from pyarchinit_mini.services.import_export_service import ImportExportService

# Database paths
MINI_DB = 'sqlite:////Users/enzo/Documents/pyarchinit-mini-desk/pyarchinit_mini.db'
SOURCE_DB = 'sqlite:////Users/enzo/pyarchinit/pyarchinit_DB_folder/my_database.sqlite'

# Initialize service
service = ImportExportService(MINI_DB, SOURCE_DB)

# Import everything for specific site(s)
site_name = 'My Site'

# 1. Import Site
print("Importing site...")
site_stats = service.import_sites(
    sito_filter=[site_name],
    auto_migrate=True,    # Add missing i18n columns
    auto_backup=True      # Create backup before migration
)
print(f"✓ Sites: {site_stats['imported']} imported, {site_stats['updated']} updated")
if site_stats.get('backup_path'):
    print(f"✓ Backup: {site_stats['backup_path']}")

# 2. Import US with Relationships
print("\nImporting US...")
us_stats = service.import_us(
    sito_filter=[site_name],
    import_relationships=True,
    auto_migrate=True,
    auto_backup=True  # Reuses existing backup
)
print(f"✓ US: {us_stats['imported']} imported, {us_stats['updated']} updated")
print(f"✓ Relationships: {us_stats['relationships_created']}")

# 3. Import Inventario
print("\nImporting inventario...")
inv_stats = service.import_inventario(
    sito_filter=[site_name],
    auto_migrate=True,
    auto_backup=True  # Reuses existing backup
)
print(f"✓ Inventario: {inv_stats['imported']} imported")

# 4. Import Periodizzazione
print("\nImporting periodizzazione...")
per_stats = service.import_periodizzazione(
    sito_filter=[site_name]
)
print(f"✓ Periodizzazione: {per_stats['imported']} imported")

# 5. Import Thesaurus (one time, no site filter)
print("\nImporting thesaurus...")
thes_stats = service.import_thesaurus()
print(f"✓ Thesaurus: {thes_stats['imported']} imported")

print("\n✓ Import complete!")

Expected Output:

Importing site...
✓ Sites: 1 imported, 0 updated
✓ Backup: /Users/enzo/pyarchinit/pyarchinit_DB_folder/my_database.sqlite.backup_20251028_143025

Importing US...
✓ US: 758 imported, 0 updated
✓ Relationships: 2459

Importing inventario...
✓ Inventario: 1234 imported

Importing periodizzazione...
✓ Periodizzazione: 42 imported

Importing thesaurus...
✓ Thesaurus: 156 imported

✓ Import complete!

Python API Integration

Using in External Projects

You can integrate PyArchInit-Mini’s import/export functionality into your own Python applications. This is particularly useful for:

  • Custom data migration tools

  • Automated synchronization scripts

  • Data pipeline integration

  • Multi-database management systems

Basic Integration Example

"""
Custom Archaeological Data Migrator

This example shows how to use PyArchInit-Mini's import service
in your own Python application.
"""

from pyarchinit_mini.services.import_export_service import ImportExportService
import logging
from pathlib import Path

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class ArchaeologicalDataMigrator:
    """Custom migrator using PyArchInit-Mini services"""

    def __init__(self, mini_db_path: str, source_db_path: str):
        """
        Initialize the migrator

        Args:
            mini_db_path: Path to PyArchInit-Mini database
            source_db_path: Path to source PyArchInit database
        """
        # Create SQLAlchemy connection strings
        self.mini_conn = f'sqlite:///{mini_db_path}'
        self.source_conn = f'sqlite:///{source_db_path}'

        # Initialize the import service
        self.service = ImportExportService(
            mini_db_connection=self.mini_conn,
            source_db_connection=self.source_conn
        )

        logger.info(f"Migrator initialized")
        logger.info(f"  Source: {source_db_path}")
        logger.info(f"  Target: {mini_db_path}")

    def migrate_site(self, site_name: str, include_media: bool = True) -> dict:
        """
        Migrate a complete archaeological site

        Args:
            site_name: Name of the site to migrate
            include_media: Whether to include inventario materiali

        Returns:
            Dictionary with migration statistics
        """
        logger.info(f"Starting migration for site: {site_name}")

        results = {
            'site': site_name,
            'statistics': {},
            'errors': []
        }

        try:
            # Step 1: Import site metadata
            logger.info("Step 1/5: Importing site metadata...")
            site_stats = self.service.import_sites(
                sito_filter=[site_name],
                auto_migrate=True,
                auto_backup=True
            )
            results['statistics']['sites'] = site_stats
            logger.info(f"  ✓ Sites: {site_stats['imported']} imported")

            # Step 2: Import stratigraphic units
            logger.info("Step 2/5: Importing stratigraphic units...")
            us_stats = self.service.import_us(
                sito_filter=[site_name],
                import_relationships=True,
                auto_migrate=True,
                auto_backup=True
            )
            results['statistics']['us'] = us_stats
            logger.info(f"  ✓ US: {us_stats['imported']} imported")
            logger.info(f"  ✓ Relationships: {us_stats.get('relationships_created', 0)}")

            # Step 3: Import periodization
            logger.info("Step 3/5: Importing periodization...")
            per_stats = self.service.import_periodizzazione(
                sito_filter=[site_name]
            )
            results['statistics']['periodizzazione'] = per_stats
            logger.info(f"  ✓ Periodizzazione: {per_stats['imported']} imported")

            # Step 4: Import material inventory (optional)
            if include_media:
                logger.info("Step 4/5: Importing material inventory...")
                inv_stats = self.service.import_inventario(
                    sito_filter=[site_name],
                    auto_migrate=True,
                    auto_backup=True
                )
                results['statistics']['inventario'] = inv_stats
                logger.info(f"  ✓ Inventario: {inv_stats['imported']} imported")
            else:
                logger.info("Step 4/5: Skipping material inventory")

            # Step 5: Import thesaurus (once per database)
            logger.info("Step 5/5: Importing thesaurus...")
            thes_stats = self.service.import_thesaurus()
            results['statistics']['thesaurus'] = thes_stats
            logger.info(f"  ✓ Thesaurus: {thes_stats['imported']} imported")

            logger.info(f"Migration complete for site: {site_name}")

        except Exception as e:
            logger.error(f"Migration failed: {str(e)}")
            results['errors'].append(str(e))

        return results

    def migrate_multiple_sites(self, site_names: list) -> dict:
        """
        Migrate multiple archaeological sites

        Args:
            site_names: List of site names to migrate

        Returns:
            Dictionary with overall migration statistics
        """
        overall_results = {
            'total_sites': len(site_names),
            'successful': 0,
            'failed': 0,
            'site_results': []
        }

        for site_name in site_names:
            logger.info(f"\n{'='*60}")
            result = self.migrate_site(site_name)
            overall_results['site_results'].append(result)

            if not result['errors']:
                overall_results['successful'] += 1
            else:
                overall_results['failed'] += 1

        logger.info(f"\n{'='*60}")
        logger.info("Overall migration summary:")
        logger.info(f"  Total sites: {overall_results['total_sites']}")
        logger.info(f"  Successful: {overall_results['successful']}")
        logger.info(f"  Failed: {overall_results['failed']}")

        return overall_results

# Usage example
if __name__ == '__main__':
    # Initialize migrator
    migrator = ArchaeologicalDataMigrator(
        mini_db_path='/path/to/pyarchinit_mini.db',
        source_db_path='/path/to/pyarchinit_source.db'
    )

    # Migrate single site
    result = migrator.migrate_site('Scavo Archeologico')

    # Or migrate multiple sites
    results = migrator.migrate_multiple_sites([
        'Site A',
        'Site B',
        'Site C'
    ])

Expected Output:

2025-10-28 14:30:25 - INFO - Migrator initialized
2025-10-28 14:30:25 - INFO -   Source: /path/to/pyarchinit_source.db
2025-10-28 14:30:25 - INFO -   Target: /path/to/pyarchinit_mini.db
2025-10-28 14:30:25 - INFO - Starting migration for site: Scavo Archeologico
2025-10-28 14:30:25 - INFO - Step 1/5: Importing site metadata...
2025-10-28 14:30:26 - INFO -   ✓ Sites: 1 imported
2025-10-28 14:30:26 - INFO - Step 2/5: Importing stratigraphic units...
2025-10-28 14:30:32 - INFO -   ✓ US: 758 imported
2025-10-28 14:30:32 - INFO -   ✓ Relationships: 2459
2025-10-28 14:30:32 - INFO - Step 3/5: Importing periodization...
2025-10-28 14:30:33 - INFO -   ✓ Periodizzazione: 42 imported
2025-10-28 14:30:33 - INFO - Step 4/5: Importing material inventory...
2025-10-28 14:30:38 - INFO -   ✓ Inventario: 1234 imported
2025-10-28 14:30:38 - INFO - Step 5/5: Importing thesaurus...
2025-10-28 14:30:39 - INFO -   ✓ Thesaurus: 156 imported
2025-10-28 14:30:39 - INFO - Migration complete for site: Scavo Archeologico

Advanced: PostgreSQL Integration

"""
PostgreSQL to PostgreSQL migration with custom configuration
"""

from pyarchinit_mini.services.import_export_service import ImportExportService
import os

class PostgreSQLMigrator:
    """Specialized migrator for PostgreSQL databases"""

    def __init__(self):
        # Read credentials from environment variables (best practice)
        source_host = os.getenv('SOURCE_PG_HOST', 'localhost')
        source_port = os.getenv('SOURCE_PG_PORT', '5432')
        source_db = os.getenv('SOURCE_PG_DB', 'pyarchinit_source')
        source_user = os.getenv('SOURCE_PG_USER', 'postgres')
        source_pass = os.getenv('SOURCE_PG_PASS', '')

        target_host = os.getenv('TARGET_PG_HOST', 'localhost')
        target_port = os.getenv('TARGET_PG_PORT', '5432')
        target_db = os.getenv('TARGET_PG_DB', 'pyarchinit_mini')
        target_user = os.getenv('TARGET_PG_USER', 'postgres')
        target_pass = os.getenv('TARGET_PG_PASS', '')

        # Build connection strings
        source_conn = (
            f'postgresql://{source_user}:{source_pass}@'
            f'{source_host}:{source_port}/{source_db}'
        )

        target_conn = (
            f'postgresql://{target_user}:{target_pass}@'
            f'{target_host}:{target_port}/{target_db}'
        )

        self.service = ImportExportService(target_conn, source_conn)

    def sync_databases(self, sites: list = None) -> dict:
        """
        Synchronize databases for specified sites

        Args:
            sites: List of site names, or None for all sites

        Returns:
            Synchronization statistics
        """
        # Import all entity types
        site_stats = self.service.import_sites(
            sito_filter=sites,
            auto_migrate=True,
            auto_backup=True
        )

        us_stats = self.service.import_us(
            sito_filter=sites,
            import_relationships=True,
            auto_migrate=True,
            auto_backup=True
        )

        inv_stats = self.service.import_inventario(
            sito_filter=sites,
            auto_migrate=True,
            auto_backup=True
        )

        per_stats = self.service.import_periodizzazione(
            sito_filter=sites
        )

        return {
            'sites': site_stats,
            'us': us_stats,
            'inventario': inv_stats,
            'periodizzazione': per_stats
        }

# Usage with environment variables
# export SOURCE_PG_HOST=sourceserver.com
# export SOURCE_PG_DB=pyarchinit_prod
# export TARGET_PG_DB=pyarchinit_mini_dev
# python migrate_postgres.py

migrator = PostgreSQLMigrator()
results = migrator.sync_databases(sites=['Site A', 'Site B'])

Configuration and Options

Import Parameters

All import functions support these parameters:

service.import_sites(
    sito_filter=['Site1', 'Site2'],  # List of sites (None = all)
    auto_migrate=True,               # Add missing i18n columns
    auto_backup=True                 # Create automatic backup
)

service.import_us(
    sito_filter=['Site1'],           # List of sites
    import_relationships=True,       # Also import relationships
    auto_migrate=True,               # Add i18n columns
    auto_backup=True                 # Automatic backup
)

service.import_inventario(
    sito_filter=['Site1'],           # List of sites
    auto_migrate=True,               # Add i18n columns
    auto_backup=True                 # Automatic backup
)

Disabling Backup

If you are absolutely certain and don’t want backup:

# WARNING: Source database will be modified WITHOUT backup!
stats = service.import_us(
    sito_filter=['Site1'],
    auto_migrate=True,
    auto_backup=False  # ⚠️ Disables backup
)

Not recommended unless:

  • Source database is a test copy

  • You already have a manual backup

  • Database is on a system with automatic backups

Disabling Migration

If the database already has i18n columns:

stats = service.import_us(
    sito_filter=['Site1'],
    auto_migrate=False,  # Don't add columns
    auto_backup=False    # No backup needed if not modifying
)

i18n Migration System

Automatically Added Columns

If the PyArchInit database doesn’t have i18n (English) columns, they are added automatically:

site_table

  • definizione_sito_en (TEXT NULL)

  • descrizione_en (TEXT NULL)

us_table

  • d_stratigrafica_en (TEXT NULL)

  • d_interpretativa_en (TEXT NULL)

  • descrizione_en (TEXT NULL)

  • interpretazione_en (TEXT NULL)

  • formazione_en (TEXT NULL)

  • stato_di_conservazione_en (TEXT NULL)

  • colore_en (TEXT NULL)

  • consistenza_en (TEXT NULL)

  • struttura_en (TEXT NULL)

  • inclusi_en (TEXT NULL)

  • campioni_en (TEXT NULL)

  • documentazione_en (TEXT NULL)

  • osservazioni_en (TEXT NULL)

inventario_materiali_table

  • tipo_reperto_en (TEXT NULL)

  • definizione_reperto_en (TEXT NULL)

  • descrizione_en (TEXT NULL)

  • tecnologia_en (TEXT NULL)

  • forma_en (TEXT NULL)

  • stato_conservazione_en (TEXT NULL)

  • osservazioni_en (TEXT NULL)

Migration Safety

Non-destructive: Only adds columns, NEVER modifies or deletes data ✅ NULL default: New columns are empty (NULL) ✅ Idempotent: Can be run multiple times safely ✅ With backup: Automatic backup before any modification ✅ Complete logging: All operations are logged

Verification

After Import - SQL Queries

# SQLite
sqlite3 pyarchinit_mini.db

# Check sites
SELECT COUNT(*) FROM site_table WHERE sito = 'My Site';

# Check US
SELECT COUNT(*) FROM us_table WHERE sito = 'My Site';

# Check relationships
SELECT COUNT(*) FROM us_relationships_table WHERE sito = 'My Site';

# Check periodizzazione
SELECT COUNT(*) FROM periodizzazione_table WHERE sito = 'My Site';

After Import - Web GUI

  1. Sites: http://localhost:5000/sites

  2. US: http://localhost:5000/us (filter by site)

  3. Harris Matrix: http://localhost:5000/harris-matrix

  4. Periodizzazione: http://localhost:5000/periodizzazione

After Import - Python API

from pyarchinit_mini.database.manager import DatabaseManager
from pyarchinit_mini.services.site_service import SiteService
from pyarchinit_mini.services.us_service import USService

# Initialize services
db_manager = DatabaseManager('sqlite:///pyarchinit_mini.db')
site_service = SiteService(db_manager)
us_service = USService(db_manager)

# Verify sites
sites = site_service.get_all()
print(f"Total sites: {len(sites)}")
for site in sites:
    print(f"  - {site['sito']}")

# Verify US for a specific site
us_list = us_service.search(sito='My Site')
print(f"US for 'My Site': {len(us_list)}")

# Verify relationships
relationships = us_service.get_relationships(sito='My Site')
print(f"Relationships: {len(relationships)}")

Backup Restoration

SQLite Restoration

# 1. Find the backup
ls -lh /path/to/pyarchinit*.backup_*

# 2. Copy backup over original
cp /path/to/pyarchinit.db.backup_20251028_143025 /path/to/pyarchinit.db

# 3. Verify
sqlite3 /path/to/pyarchinit.db "SELECT COUNT(*) FROM us_table"

PostgreSQL Restoration

# 1. Find the backup SQL file
ls -lh *_backup_*.sql

# 2. Drop and recreate database (CAREFUL!)
dropdb my_database
createdb my_database

# 3. Restore
psql my_database < my_database_backup_20251028_143025.sql

# 4. Verify
psql my_database -c "SELECT COUNT(*) FROM us_table"

Import Checklist

Before Importing

  • Manual backup exists? (extra safety)

  • Source database correct? (verify path/credentials)

  • Sufficient disk space? (for automatic backup)

  • Flask server/Desktop GUI running?

  • PyArchInit-Mini database initialized?

During Import

  • Monitor logs (Web GUI console or CLI output)

  • Verify backup created (path shown in logs)

  • Wait for completion (don’t interrupt!)

After Import

  • Verify counts (sites, US, relationships)

  • Check web interface (visualize data)

  • Test Harris Matrix (generate and view)

  • Backup Mini database (cp pyarchinit_mini.db)

Practical Examples

Example 1: Single Site Import

from pyarchinit_mini.services.import_export_service import ImportExportService

service = ImportExportService(
    'sqlite:///pyarchinit_mini.db',
    'sqlite:////Users/enzo/pyarchinit/my_site.db'
)

# Import everything for a specific site
site_name = 'Scavo archeologico'

service.import_sites(sito_filter=[site_name])
service.import_us(sito_filter=[site_name], import_relationships=True)
service.import_inventario(sito_filter=[site_name])
service.import_periodizzazione(sito_filter=[site_name])

Output:

INFO: Creating backup: /Users/enzo/pyarchinit/my_site.db.backup_20251028_143025
INFO: Sites imported: 1
INFO: US imported: 125, Relationships: 456
INFO: Inventario imported: 234
INFO: Periodizzazione imported: 18

Example 2: Complete Import (All Sites)

service = ImportExportService(
    'sqlite:///pyarchinit_mini.db',
    'sqlite:////Users/enzo/pyarchinit/all_sites.db'
)

# Import EVERYTHING (no site filter)
service.import_sites()  # All sites
service.import_us(import_relationships=True)  # All US
service.import_inventario()  # All inventario
service.import_periodizzazione()  # All periodizzazione
service.import_thesaurus()  # Thesaurus (once)

Example 3: PostgreSQL Import

service = ImportExportService(
    mini_db_connection='sqlite:///pyarchinit_mini.db',
    source_db_connection='postgresql://user:password@localhost:5432/pyarchinit_db'
)

# Import works identically
service.import_sites(sito_filter=['Site1'])
service.import_us(sito_filter=['Site1'], import_relationships=True)

Example 4: Selective Import with Error Handling

from pyarchinit_mini.services.import_export_service import ImportExportService
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def safe_import(mini_db: str, source_db: str, sites: list):
    """
    Import with comprehensive error handling

    Args:
        mini_db: Target database connection string
        source_db: Source database connection string
        sites: List of site names to import

    Returns:
        dict: Import statistics or error information
    """
    try:
        service = ImportExportService(mini_db, source_db)

        results = {
            'success': True,
            'sites': [],
            'errors': []
        }

        for site in sites:
            try:
                logger.info(f"Importing {site}...")

                # Import with full error tracking
                site_stats = service.import_sites(
                    sito_filter=[site],
                    auto_migrate=True,
                    auto_backup=True
                )

                us_stats = service.import_us(
                    sito_filter=[site],
                    import_relationships=True,
                    auto_migrate=True,
                    auto_backup=True
                )

                results['sites'].append({
                    'name': site,
                    'imported': True,
                    'us_count': us_stats['imported'],
                    'rel_count': us_stats.get('relationships_created', 0)
                })

                logger.info(f"✓ {site}: {us_stats['imported']} US imported")

            except Exception as e:
                logger.error(f"✗ {site}: {str(e)}")
                results['errors'].append({
                    'site': site,
                    'error': str(e)
                })

        if results['errors']:
            results['success'] = False

        return results

    except Exception as e:
        logger.error(f"Fatal error: {str(e)}")
        return {
            'success': False,
            'error': str(e)
        }

# Usage
results = safe_import(
    mini_db='sqlite:///pyarchinit_mini.db',
    source_db='sqlite:///source.db',
    sites=['Site A', 'Site B', 'Site C']
)

if results['success']:
    print(f"✓ Successfully imported {len(results['sites'])} sites")
else:
    print(f"✗ Import failed with {len(results['errors'])} errors")

Backup Management

Cleanup Old Backups

Backups accumulate over time. Clean them periodically:

# List all backups
ls -lh /path/to/pyarchinit*.backup_*

# Remove backups older than 30 days
find /path/to/pyarchinit_DB_folder -name "*.backup_*" -mtime +30 -delete

# Or manually
rm /path/to/pyarchinit.db.backup_20251001_*

Compressed Backups

To save disk space:

# Compress SQLite backup
gzip /path/to/pyarchinit.db.backup_20251028_143025

# Decompress when needed
gunzip /path/to/pyarchinit.db.backup_20251028_143025.gz

FAQ

Q: Is backup created every time?

A: Only on the first import/migration per session. Subsequent imports in the same session reuse the same backup.

service = ImportExportService(...)

# First import -> Backup created
service.import_sites()  # ✓ Backup created

# Subsequent imports -> Reuse backup
service.import_us()  # ✓ Using existing backup
service.import_inventario()  # ✓ Using existing backup

Q: Where are backups saved?

A:

  • SQLite: Same directory as the original database

  • PostgreSQL: Current directory where you run the script

Q: Does backup slow down import?

A: Minimally. For SQLite, it’s a file copy (fast). For PostgreSQL, it uses pg_dump (can take longer for large databases).

Q: Can I have multiple backups?

A: Yes! Each backup has a unique timestamp. They don’t overwrite previous backups.

Q: What if backup fails?

A: Import continues with a warning, but it’s strongly discouraged to proceed if backup fails.

Q: Is the original database modified?

A: Yes, IF i18n columns need to be added. But ONLY after backup is created. Existing data is NEVER modified.

API Reference

ImportExportService Class

class ImportExportService:
    """
    Service for importing/exporting data between PyArchInit and PyArchInit-Mini
    """

    def __init__(
        self,
        mini_db_connection: str,
        source_db_connection: str
    ):
        """
        Initialize the import/export service

        Args:
            mini_db_connection: SQLAlchemy connection string for PyArchInit-Mini
            source_db_connection: SQLAlchemy connection string for source database
        """
        pass

    def import_sites(
        self,
        sito_filter: list = None,
        auto_migrate: bool = True,
        auto_backup: bool = True
    ) -> dict:
        """
        Import sites from source database

        Args:
            sito_filter: List of site names to import (None = all)
            auto_migrate: Add missing i18n columns automatically
            auto_backup: Create backup before modifications

        Returns:
            dict: Statistics with 'imported', 'updated', 'backup_path' keys
        """
        pass

    def import_us(
        self,
        sito_filter: list = None,
        import_relationships: bool = True,
        auto_migrate: bool = True,
        auto_backup: bool = True
    ) -> dict:
        """
        Import stratigraphic units from source database

        Args:
            sito_filter: List of site names to import (None = all)
            import_relationships: Also import US relationships
            auto_migrate: Add missing i18n columns automatically
            auto_backup: Create backup before modifications

        Returns:
            dict: Statistics with 'imported', 'updated', 'relationships_created' keys
        """
        pass

    def import_inventario(
        self,
        sito_filter: list = None,
        auto_migrate: bool = True,
        auto_backup: bool = True
    ) -> dict:
        """
        Import material inventory from source database

        Args:
            sito_filter: List of site names to import (None = all)
            auto_migrate: Add missing i18n columns automatically
            auto_backup: Create backup before modifications

        Returns:
            dict: Statistics with 'imported', 'updated' keys
        """
        pass

    def import_periodizzazione(
        self,
        sito_filter: list = None
    ) -> dict:
        """
        Import periodization data from source database

        Args:
            sito_filter: List of site names to import (None = all)

        Returns:
            dict: Statistics with 'imported', 'updated' keys
        """
        pass

    def import_thesaurus(self) -> dict:
        """
        Import thesaurus data from source database

        Note: Thesaurus is global, not site-specific

        Returns:
            dict: Statistics with 'imported', 'updated' keys
        """
        pass

Summary

✅ Complete System

  1. Automatic Backup: Always created before modifications

  2. i18n Migration: Columns added automatically

  3. Complete Import: Sites, US, Relationships, Inventario, Periodizzazione

  4. All Interfaces: Web GUI, Desktop GUI, CLI, Python API

  5. SQLite and PostgreSQL: Both supported

  6. Safe and Tested: Tested with real databases (Dom zu Lund, 758 US)

Import Statistics Example

Dom zu Lund archaeological site:

  • Backup: 4.7 MB (from 5.8 MB database)

  • Sites: 1 imported

  • US: 758 imported

  • Relationships: 2,459 created

  • Periodizzazione: 42 records

  • Time: ~30-60 seconds (depends on size)

See Also

The import system is now fully automated, safe, and production-ready! 🚀