notion2pg-bulk


Namenotion2pg-bulk JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryA Python package that automatically finds and migrates to PostgreSQL all databases in a Notion workspace.
upload_time2025-08-22 21:33:23
maintainerNone
docs_urlNone
authorbenvigano
requires_python>=3.8
licenseGPL-3.0-or-later
keywords notion postgresql migration database export workspace notion export notion migrate
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # notion2pg_bulk

- Automatically discovers and migrates **all databases in a workspace** regardless of their views or position in the page structure
- Preserves **database descriptions and property descriptions**
- Supports **relation properties** using PostgreSQL arrays
- **Select field support**: Single and multi-select options stored in separate lookup tables with foreign key constraints
- Complies with Notion API limits (3 requests/second average)

## Installation
```bash
pip install notion2pg-bulk
```

## Setup and Usage

### Requirements
- a **Notion API key** connected to all the databased that you wish to migrate (note: Notion now allows to connect databases ditectly from the integration configuration page, under the 'Access' tab. For quickly connecting **all databases** in a workspace, just tick all top level pages.
- PostgreSQL database connection URL

### Interactive Mode
**On (Default):**
- Dispays detected databases and fields and asks for confirmation before running the migration
- Progress bar
- Shows post-migration notes

**Off:**
(`--quiet` flag in CLI or set `interactive_mode=False` in Python API)
- `.run()` runs migration directly and silently

### CLI
**Options:**
- `--notion-token`: Notion integration token (or set `NOTION_TOKEN` env var)
- `--database-url`: PostgreSQL connection string (or set `DATABASE_URL` env var)
- `--quiet`: Run in non-interactive mode (skip validation steps and progress bars)
- `--extract-page-content`: Extract free-form content from page bodies (slower migration)

**Examples:**
```bash
# Interactive mode (default)
notion2pg-bulk --notion-token "your_token" --database-url "postgresql://..."

# Non-interactive mode (skip validation steps)
notion2pg-bulk --notion-token "your_token" --database-url "postgresql://..." --quiet

# Extract page content (slower but includes free-form content)
notion2pg-bulk --notion-token "your_token" --database-url "postgresql://..." --extract-page-content

# Non-interactive with page content extraction
notion2pg-bulk --notion-token "your_token" --database-url "postgresql://..." --quiet --extract-page-content
```

### Python API:
```python
from notion2pg_bulk import NotionMigrator
import sqlalchemy as sa

engine = sa.create_engine('postgresql://user:password@localhost/dbname')
migrator = NotionMigrator(
    notion_token="your_notion_integration_token",
    db_connection=engine,
    interactive_mode=True,
    extract_page_content=True,
)
migrator.run()
```

## Property Type Mapping

| Notion Property | PostgreSQL Type | Notes |
|----------------|-----------------|-------|
| Title | `TEXT` | Primary identifier |
| Rich Text | `TEXT` | Preserved as markdown with formatting |
| Number | `NUMERIC` | |
| Select | `TEXT` | Single option value + lookup table with foreign key |
| Multi-select | `TEXT[]` | Array of option values + lookup table with check constraints |
| Date | `TIMESTAMP` | |
| Checkbox | `BOOLEAN` | |
| URL | `TEXT` | |
| Email | `TEXT` | |
| Phone | `TEXT` | |
| Relation | `TEXT[]` | Array of related page IDs |
| People | `TEXT[]` | Array of user IDs |
| Files | `TEXT[]` | Array of file URLs |
| Created time | `TIMESTAMP` | |
| Created by | `TEXT` | User ID |
| Last edited time | `TIMESTAMP` | |
| Last edited by | `TEXT` | User ID |
| Formula | - | ⚠️ Skipped (not supported by Notion API) |
| Rollup | - | ⚠️ Skipped (not supported by Notion API) |

## Additional Page Content Mode

The migrator can optionally extract free-form content from database pages. Extracted content is stored in the `additional_page_content` column as plain text.

```python
migrator = NotionMigrator(
    notion_token=token,
    db_connection=engine,
    extract_page_content=True  # Default is false
)
```

**Supported blocks:**
- Paragraph text
- Headings (all levels)
- Bulleted and numbered lists
- Code blocks
- To-do items
- Callouts
- Toggle blocks
- Dividers
- Embedded databases (ID reference only)

**Unsupported blocks:**
- Images and media files
- Complex block types (equations, embeds, etc.)
- Block formatting and styling
- Page hierarchies and relationships

**Post-migration analysis:**
When page content extraction is enabled, the migrator provides a comprehensive summary of:
- Unsupported block types found and their locations (grouped by record)
- Embedded databases that were referenced in page content but not connected to the integration (with full database IDs)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "notion2pg-bulk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "notion, postgresql, migration, database, export, workspace, notion export, notion migrate",
    "author": "benvigano",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/6a/6b/9240816f67d4b673ce499534265d719f209a8266ed0707bc1bac3cd4696d/notion2pg_bulk-0.1.0.tar.gz",
    "platform": null,
    "description": "# notion2pg_bulk\r\n\r\n- Automatically discovers and migrates **all databases in a workspace** regardless of their views or position in the page structure\r\n- Preserves **database descriptions and property descriptions**\r\n- Supports **relation properties** using PostgreSQL arrays\r\n- **Select field support**: Single and multi-select options stored in separate lookup tables with foreign key constraints\r\n- Complies with Notion API limits (3 requests/second average)\r\n\r\n## Installation\r\n```bash\r\npip install notion2pg-bulk\r\n```\r\n\r\n## Setup and Usage\r\n\r\n### Requirements\r\n- a **Notion API key** connected to all the databased that you wish to migrate (note: Notion now allows to connect databases ditectly from the integration configuration page, under the 'Access' tab. For quickly connecting **all databases** in a workspace, just tick all top level pages.\r\n- PostgreSQL database connection URL\r\n\r\n### Interactive Mode\r\n**On (Default):**\r\n- Dispays detected databases and fields and asks for confirmation before running the migration\r\n- Progress bar\r\n- Shows post-migration notes\r\n\r\n**Off:**\r\n(`--quiet` flag in CLI or set `interactive_mode=False` in Python API)\r\n- `.run()` runs migration directly and silently\r\n\r\n### CLI\r\n**Options:**\r\n- `--notion-token`: Notion integration token (or set `NOTION_TOKEN` env var)\r\n- `--database-url`: PostgreSQL connection string (or set `DATABASE_URL` env var)\r\n- `--quiet`: Run in non-interactive mode (skip validation steps and progress bars)\r\n- `--extract-page-content`: Extract free-form content from page bodies (slower migration)\r\n\r\n**Examples:**\r\n```bash\r\n# Interactive mode (default)\r\nnotion2pg-bulk --notion-token \"your_token\" --database-url \"postgresql://...\"\r\n\r\n# Non-interactive mode (skip validation steps)\r\nnotion2pg-bulk --notion-token \"your_token\" --database-url \"postgresql://...\" --quiet\r\n\r\n# Extract page content (slower but includes free-form content)\r\nnotion2pg-bulk --notion-token \"your_token\" --database-url \"postgresql://...\" --extract-page-content\r\n\r\n# Non-interactive with page content extraction\r\nnotion2pg-bulk --notion-token \"your_token\" --database-url \"postgresql://...\" --quiet --extract-page-content\r\n```\r\n\r\n### Python API:\r\n```python\r\nfrom notion2pg_bulk import NotionMigrator\r\nimport sqlalchemy as sa\r\n\r\nengine = sa.create_engine('postgresql://user:password@localhost/dbname')\r\nmigrator = NotionMigrator(\r\n    notion_token=\"your_notion_integration_token\",\r\n    db_connection=engine,\r\n    interactive_mode=True,\r\n    extract_page_content=True,\r\n)\r\nmigrator.run()\r\n```\r\n\r\n## Property Type Mapping\r\n\r\n| Notion Property | PostgreSQL Type | Notes |\r\n|----------------|-----------------|-------|\r\n| Title | `TEXT` | Primary identifier |\r\n| Rich Text | `TEXT` | Preserved as markdown with formatting |\r\n| Number | `NUMERIC` | |\r\n| Select | `TEXT` | Single option value + lookup table with foreign key |\r\n| Multi-select | `TEXT[]` | Array of option values + lookup table with check constraints |\r\n| Date | `TIMESTAMP` | |\r\n| Checkbox | `BOOLEAN` | |\r\n| URL | `TEXT` | |\r\n| Email | `TEXT` | |\r\n| Phone | `TEXT` | |\r\n| Relation | `TEXT[]` | Array of related page IDs |\r\n| People | `TEXT[]` | Array of user IDs |\r\n| Files | `TEXT[]` | Array of file URLs |\r\n| Created time | `TIMESTAMP` | |\r\n| Created by | `TEXT` | User ID |\r\n| Last edited time | `TIMESTAMP` | |\r\n| Last edited by | `TEXT` | User ID |\r\n| Formula | - | \u26a0\ufe0f Skipped (not supported by Notion API) |\r\n| Rollup | - | \u26a0\ufe0f Skipped (not supported by Notion API) |\r\n\r\n## Additional Page Content Mode\r\n\r\nThe migrator can optionally extract free-form content from database pages. Extracted content is stored in the `additional_page_content` column as plain text.\r\n\r\n```python\r\nmigrator = NotionMigrator(\r\n    notion_token=token,\r\n    db_connection=engine,\r\n    extract_page_content=True  # Default is false\r\n)\r\n```\r\n\r\n**Supported blocks:**\r\n- Paragraph text\r\n- Headings (all levels)\r\n- Bulleted and numbered lists\r\n- Code blocks\r\n- To-do items\r\n- Callouts\r\n- Toggle blocks\r\n- Dividers\r\n- Embedded databases (ID reference only)\r\n\r\n**Unsupported blocks:**\r\n- Images and media files\r\n- Complex block types (equations, embeds, etc.)\r\n- Block formatting and styling\r\n- Page hierarchies and relationships\r\n\r\n**Post-migration analysis:**\r\nWhen page content extraction is enabled, the migrator provides a comprehensive summary of:\r\n- Unsupported block types found and their locations (grouped by record)\r\n- Embedded databases that were referenced in page content but not connected to the integration (with full database IDs)\r\n",
    "bugtrack_url": null,
    "license": "GPL-3.0-or-later",
    "summary": "A Python package that automatically finds and migrates to PostgreSQL all databases in a Notion workspace.",
    "version": "0.1.0",
    "project_urls": {
        "Homepage": "https://github.com/benvigano/notion2pg-bulk",
        "Issues": "https://github.com/benvigano/notion2pg-bulk/issues",
        "Repository": "https://github.com/benvigano/notion2pg-bulk"
    },
    "split_keywords": [
        "notion",
        " postgresql",
        " migration",
        " database",
        " export",
        " workspace",
        " notion export",
        " notion migrate"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6a0fdef6d837160d39cd6ccc272ac4226ee9a9c1dcf1f5b795f9d20b02ac6216",
                "md5": "9bca8672bbfec7fe4dd26449172b682a",
                "sha256": "9ee328f707369ba6518e03219bd91010e35fc8a432e0fee628ec82c278d32b10"
            },
            "downloads": -1,
            "filename": "notion2pg_bulk-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9bca8672bbfec7fe4dd26449172b682a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 16930,
            "upload_time": "2025-08-22T21:33:21",
            "upload_time_iso_8601": "2025-08-22T21:33:21.728897Z",
            "url": "https://files.pythonhosted.org/packages/6a/0f/def6d837160d39cd6ccc272ac4226ee9a9c1dcf1f5b795f9d20b02ac6216/notion2pg_bulk-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6a6b9240816f67d4b673ce499534265d719f209a8266ed0707bc1bac3cd4696d",
                "md5": "14f07fff3f7eeb64ea3c4fc837a349f5",
                "sha256": "67bdc104fb3cb0eb28e06f1ac1791a70ac9184496e8f817299d8b36f91f743d9"
            },
            "downloads": -1,
            "filename": "notion2pg_bulk-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "14f07fff3f7eeb64ea3c4fc837a349f5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 14234,
            "upload_time": "2025-08-22T21:33:23",
            "upload_time_iso_8601": "2025-08-22T21:33:23.085970Z",
            "url": "https://files.pythonhosted.org/packages/6a/6b/9240816f67d4b673ce499534265d719f209a8266ed0707bc1bac3cd4696d/notion2pg_bulk-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-22 21:33:23",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "benvigano",
    "github_project": "notion2pg-bulk",
    "github_not_found": true,
    "lcname": "notion2pg-bulk"
}
        
Elapsed time: 1.03231s