# Django Electric
A Django integration package for [Electric SQL](https://electric-sql.com/), enabling real-time data synchronization between Django applications and client devices.
[](https://badge.fury.io/py/django-electric)
[](https://pypi.org/project/django-electric/)
[](https://www.djangoproject.com/)
[](https://opensource.org/licenses/Apache-2.0)
## What is Electric SQL?
Electric SQL is a sync engine that enables local-first development with real-time synchronization. Instead of traditional request-response patterns, Electric provides efficient delta-based syncing between your backend database and client applications.
## Features
- **Seamless Django Integration**: Works naturally with Django ORM and existing models
- **Real-time Sync**: Bidirectional synchronization between Django and Electric SQL
- **Shape-based Sync**: Sync specific data subsets using SQL-like filters
- **Offline-First**: Build applications that work offline and sync when connected
- **Type-Safe**: Full type hints and mypy support
- **Battle-Tested**: Comprehensive test suite with pytest
- **Developer-Friendly**: Management commands, admin integration, and decorators
- **Signals Support**: React to sync events with Django signals
- **Caching**: Built-in caching for sync operations
## Installation
```bash
pip install django-electric
```
## Quick Start
### 1. Add to `INSTALLED_APPS`
```python
# settings.py
INSTALLED_APPS = [
...
'django_electric',
...
]
```
### 2. Configure Electric SQL
```python
# settings.py
# Electric service URL (required)
ELECTRIC_SERVICE_URL = 'http://localhost:5133'
# Optional settings
ELECTRIC_AUTH_TOKEN = 'your-auth-token' # If using authentication
ELECTRIC_AUTO_SYNC = True # Auto-sync on model save
ELECTRIC_SYNC_BATCH_SIZE = 100 # Batch size for sync operations
ELECTRIC_TIMEOUT = 30 # Request timeout in seconds
```
### 3. Update Your Models
```python
from django.db import models
from django_electric.models import ElectricSyncMixin
from django_electric.managers import ElectricManager
class Article(ElectricSyncMixin, models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
# Use Electric manager for sync capabilities
objects = ElectricManager()
class Meta:
electric_sync = True # Enable sync for this model
electric_where = "published = true" # Only sync published articles
```
### 4. Sync Your Data
```python
# Sync to Electric
result = Article.electric_sync()
print(f"Shape ID: {result['shape_id']}")
# Pull data from Electric
stats = Article.electric_pull()
print(f"Created: {stats['created']}, Updated: {stats['updated']}")
# Get synced data
articles = Article.electric_get_data(limit=50)
```
### 5. Use Management Commands
```bash
# Check Electric status
python manage.py electric_status
# Sync all models
python manage.py electric_sync --all
# Sync specific model
python manage.py electric_sync --model myapp.Article
# Pull data from Electric
python manage.py electric_sync --model myapp.Article --pull
```
## Documentation
### Core Concepts
#### Shape-Based Syncing
Electric SQL uses "shapes" to define what data to sync. A shape is a subset of your data defined by:
- **Table**: Which model/table to sync
- **Where clause**: SQL filter for the data
- **Columns**: Specific fields to include
- **Include**: Related models to sync
```python
# Sync only published articles
Article.electric_sync(where="published = true")
# Sync with specific columns
shape = Article.get_electric_shape(
columns=['id', 'title', 'created_at']
)
```
#### Model Configuration
Configure sync behavior in your model's `Meta` class:
```python
class Meta:
electric_sync = True # Enable sync
electric_where = "status = 'active'" # Default filter
electric_columns = ['id', 'name', 'email'] # Specific columns
```
### API Reference
#### Model Methods
**`Model.electric_sync(where=None, force=False)`**
Sync model to Electric SQL.
```python
Article.electric_sync(where="published = true", force=True)
```
**`Model.electric_pull(where=None, update_existing=True)`**
Pull data from Electric to local database.
```python
stats = Article.electric_pull(where="created_at > '2024-01-01'")
```
**`Model.electric_get_data(where=None, offset=0, limit=100)`**
Get synced data from Electric.
```python
articles = Article.electric_get_data(limit=50)
```
#### Decorators
**`@electric_cached(timeout=300)`**
Cache Electric sync results.
```python
from django_electric.decorators import electric_cached
@electric_cached(timeout=600)
def get_articles():
return Article.electric_get_data()
```
**`@electric_retry(max_attempts=3, delay=1.0)`**
Retry sync operations on failure.
```python
from django_electric.decorators import electric_retry
@electric_retry(max_attempts=5)
def sync_all_data():
Article.electric_sync()
Comment.electric_sync()
```
#### Client API
For advanced usage, use the `ElectricClient` directly:
```python
from django_electric.client import ElectricClient
with ElectricClient() as client:
# Create a shape
shape = client.create_shape(
table="articles",
where="published = true",
columns=["id", "title", "content"]
)
# Sync the shape
result = client.sync_shape(shape)
# Get shape data
data = client.get_shape_data(result['shape_id'])
```
### Management Commands
#### `electric_status`
Check Electric SQL connection and configuration.
```bash
python manage.py electric_status
```
#### `electric_sync`
Sync models with Electric SQL.
```bash
# Sync all models
python manage.py electric_sync --all
# Sync specific model
python manage.py electric_sync --model blog.Post
# Sync with custom filter
python manage.py electric_sync --model blog.Post --where "published = true"
# Force sync (ignore cache)
python manage.py electric_sync --model blog.Post --force
# Pull data from Electric
python manage.py electric_sync --model blog.Post --pull
```
### Django Admin Integration
Add Electric sync to your admin actions:
```python
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
actions = ['sync_to_electric', 'pull_from_electric']
def sync_to_electric(self, request, queryset):
result = Article.electric_sync()
self.message_user(request, f"Synced: {result}")
def pull_from_electric(self, request, queryset):
stats = Article.electric_pull()
self.message_user(
request,
f"Created: {stats['created']}, Updated: {stats['updated']}"
)
```
### Signals
React to sync events:
```python
from django_electric.signals import (
electric_sync_started,
electric_sync_completed,
electric_sync_failed,
)
@receiver(electric_sync_completed)
def on_sync_complete(sender, **kwargs):
print(f"Sync completed for {sender.__name__}")
@receiver(electric_sync_failed)
def on_sync_failed(sender, error, **kwargs):
print(f"Sync failed: {error}")
```
## Examples
See the [examples/demo_project](examples/demo_project) directory for a complete working Django application demonstrating:
- Model configuration with Electric sync
- Management command usage
- Admin panel integration
- API views with sync operations
- Decorator usage
## Development
### Setup Development Environment
```bash
# Clone the repository
git clone https://github.com/Apoorvgarg-Creator/dj-electric.git
cd django-electric
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
```
### Running Tests
```bash
# Run all tests
pytest
# Run with coverage
pytest --cov=django_electric
# Run specific test file
pytest tests/test_client.py
# Run in watch mode
pytest-watch
```
### Code Quality
```bash
# Format code
black .
isort .
# Lint
flake8 django_electric
mypy django_electric
# Type checking
mypy django_electric
```
## Contributing
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Add tests for your changes
5. Ensure all tests pass (`pytest`)
6. Commit your changes (`git commit -m 'Add amazing feature'`)
7. Push to the branch (`git push origin feature/amazing-feature`)
8. Open a Pull Request
## Publishing to PyPI
```bash
# Build the package
python -m build
# Upload to PyPI (requires credentials)
twine upload dist/*
```
## Requirements
- Python >= 3.9
- Django >= 4.2
- Electric SQL service running
## License
Apache License 2.0 - see [LICENSE](LICENSE) for details.
## Support
- **Issues**: [GitHub Issues](https://github.com/Apoorvgarg-Creator/dj-electric/issues)
- **Discussions**: [GitHub Discussions](https://github.com/Apoorvgarg-Creator/dj-electric/discussions)
- **Documentation**: [Wiki](https://github.com/Apoorvgarg-Creator/dj-electric/wiki)
## Acknowledgments
- Built for [Electric SQL](https://electric-sql.com/)
- Inspired by local-first and offline-first architectures
- Thanks to the Django and Electric SQL communities
## Roadmap
- [ ] WebSocket support for real-time updates
- [ ] Conflict resolution strategies
- [ ] Multi-tenancy support
- [ ] GraphQL integration
- [ ] Django REST Framework integration
- [ ] Async support with Django 4.2+
- [ ] Schema migration tools
- [ ] Performance monitoring and metrics
---
Made with ❤️ for the Django and Electric SQL communities
Raw data
{
"_id": null,
"home_page": null,
"name": "django-electric",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "django, electric-sql, sync, real-time, offline-first, local-first",
"author": null,
"author_email": "Your Name <your.email@example.com>",
"download_url": "https://files.pythonhosted.org/packages/24/86/19cbbc07c8e955c574cd2d36292d97ab54cbfe24bf8ac9038467a722f489/django_electric-0.1.1.tar.gz",
"platform": null,
"description": "# Django Electric\n\nA Django integration package for [Electric SQL](https://electric-sql.com/), enabling real-time data synchronization between Django applications and client devices.\n\n[](https://badge.fury.io/py/django-electric)\n[](https://pypi.org/project/django-electric/)\n[](https://www.djangoproject.com/)\n[](https://opensource.org/licenses/Apache-2.0)\n\n## What is Electric SQL?\n\nElectric SQL is a sync engine that enables local-first development with real-time synchronization. Instead of traditional request-response patterns, Electric provides efficient delta-based syncing between your backend database and client applications.\n\n## Features\n\n- **Seamless Django Integration**: Works naturally with Django ORM and existing models\n- **Real-time Sync**: Bidirectional synchronization between Django and Electric SQL\n- **Shape-based Sync**: Sync specific data subsets using SQL-like filters\n- **Offline-First**: Build applications that work offline and sync when connected\n- **Type-Safe**: Full type hints and mypy support\n- **Battle-Tested**: Comprehensive test suite with pytest\n- **Developer-Friendly**: Management commands, admin integration, and decorators\n- **Signals Support**: React to sync events with Django signals\n- **Caching**: Built-in caching for sync operations\n\n## Installation\n\n```bash\npip install django-electric\n```\n\n## Quick Start\n\n### 1. Add to `INSTALLED_APPS`\n\n```python\n# settings.py\nINSTALLED_APPS = [\n ...\n 'django_electric',\n ...\n]\n```\n\n### 2. Configure Electric SQL\n\n```python\n# settings.py\n\n# Electric service URL (required)\nELECTRIC_SERVICE_URL = 'http://localhost:5133'\n\n# Optional settings\nELECTRIC_AUTH_TOKEN = 'your-auth-token' # If using authentication\nELECTRIC_AUTO_SYNC = True # Auto-sync on model save\nELECTRIC_SYNC_BATCH_SIZE = 100 # Batch size for sync operations\nELECTRIC_TIMEOUT = 30 # Request timeout in seconds\n```\n\n### 3. Update Your Models\n\n```python\nfrom django.db import models\nfrom django_electric.models import ElectricSyncMixin\nfrom django_electric.managers import ElectricManager\n\nclass Article(ElectricSyncMixin, models.Model):\n title = models.CharField(max_length=200)\n content = models.TextField()\n published = models.BooleanField(default=False)\n created_at = models.DateTimeField(auto_now_add=True)\n\n # Use Electric manager for sync capabilities\n objects = ElectricManager()\n\n class Meta:\n electric_sync = True # Enable sync for this model\n electric_where = \"published = true\" # Only sync published articles\n```\n\n### 4. Sync Your Data\n\n```python\n# Sync to Electric\nresult = Article.electric_sync()\nprint(f\"Shape ID: {result['shape_id']}\")\n\n# Pull data from Electric\nstats = Article.electric_pull()\nprint(f\"Created: {stats['created']}, Updated: {stats['updated']}\")\n\n# Get synced data\narticles = Article.electric_get_data(limit=50)\n```\n\n### 5. Use Management Commands\n\n```bash\n# Check Electric status\npython manage.py electric_status\n\n# Sync all models\npython manage.py electric_sync --all\n\n# Sync specific model\npython manage.py electric_sync --model myapp.Article\n\n# Pull data from Electric\npython manage.py electric_sync --model myapp.Article --pull\n```\n\n## Documentation\n\n### Core Concepts\n\n#### Shape-Based Syncing\n\nElectric SQL uses \"shapes\" to define what data to sync. A shape is a subset of your data defined by:\n\n- **Table**: Which model/table to sync\n- **Where clause**: SQL filter for the data\n- **Columns**: Specific fields to include\n- **Include**: Related models to sync\n\n```python\n# Sync only published articles\nArticle.electric_sync(where=\"published = true\")\n\n# Sync with specific columns\nshape = Article.get_electric_shape(\n columns=['id', 'title', 'created_at']\n)\n```\n\n#### Model Configuration\n\nConfigure sync behavior in your model's `Meta` class:\n\n```python\nclass Meta:\n electric_sync = True # Enable sync\n electric_where = \"status = 'active'\" # Default filter\n electric_columns = ['id', 'name', 'email'] # Specific columns\n```\n\n### API Reference\n\n#### Model Methods\n\n**`Model.electric_sync(where=None, force=False)`**\n\nSync model to Electric SQL.\n\n```python\nArticle.electric_sync(where=\"published = true\", force=True)\n```\n\n**`Model.electric_pull(where=None, update_existing=True)`**\n\nPull data from Electric to local database.\n\n```python\nstats = Article.electric_pull(where=\"created_at > '2024-01-01'\")\n```\n\n**`Model.electric_get_data(where=None, offset=0, limit=100)`**\n\nGet synced data from Electric.\n\n```python\narticles = Article.electric_get_data(limit=50)\n```\n\n#### Decorators\n\n**`@electric_cached(timeout=300)`**\n\nCache Electric sync results.\n\n```python\nfrom django_electric.decorators import electric_cached\n\n@electric_cached(timeout=600)\ndef get_articles():\n return Article.electric_get_data()\n```\n\n**`@electric_retry(max_attempts=3, delay=1.0)`**\n\nRetry sync operations on failure.\n\n```python\nfrom django_electric.decorators import electric_retry\n\n@electric_retry(max_attempts=5)\ndef sync_all_data():\n Article.electric_sync()\n Comment.electric_sync()\n```\n\n#### Client API\n\nFor advanced usage, use the `ElectricClient` directly:\n\n```python\nfrom django_electric.client import ElectricClient\n\nwith ElectricClient() as client:\n # Create a shape\n shape = client.create_shape(\n table=\"articles\",\n where=\"published = true\",\n columns=[\"id\", \"title\", \"content\"]\n )\n\n # Sync the shape\n result = client.sync_shape(shape)\n\n # Get shape data\n data = client.get_shape_data(result['shape_id'])\n```\n\n### Management Commands\n\n#### `electric_status`\n\nCheck Electric SQL connection and configuration.\n\n```bash\npython manage.py electric_status\n```\n\n#### `electric_sync`\n\nSync models with Electric SQL.\n\n```bash\n# Sync all models\npython manage.py electric_sync --all\n\n# Sync specific model\npython manage.py electric_sync --model blog.Post\n\n# Sync with custom filter\npython manage.py electric_sync --model blog.Post --where \"published = true\"\n\n# Force sync (ignore cache)\npython manage.py electric_sync --model blog.Post --force\n\n# Pull data from Electric\npython manage.py electric_sync --model blog.Post --pull\n```\n\n### Django Admin Integration\n\nAdd Electric sync to your admin actions:\n\n```python\nfrom django.contrib import admin\nfrom .models import Article\n\n@admin.register(Article)\nclass ArticleAdmin(admin.ModelAdmin):\n actions = ['sync_to_electric', 'pull_from_electric']\n\n def sync_to_electric(self, request, queryset):\n result = Article.electric_sync()\n self.message_user(request, f\"Synced: {result}\")\n\n def pull_from_electric(self, request, queryset):\n stats = Article.electric_pull()\n self.message_user(\n request,\n f\"Created: {stats['created']}, Updated: {stats['updated']}\"\n )\n```\n\n### Signals\n\nReact to sync events:\n\n```python\nfrom django_electric.signals import (\n electric_sync_started,\n electric_sync_completed,\n electric_sync_failed,\n)\n\n@receiver(electric_sync_completed)\ndef on_sync_complete(sender, **kwargs):\n print(f\"Sync completed for {sender.__name__}\")\n\n@receiver(electric_sync_failed)\ndef on_sync_failed(sender, error, **kwargs):\n print(f\"Sync failed: {error}\")\n```\n\n## Examples\n\nSee the [examples/demo_project](examples/demo_project) directory for a complete working Django application demonstrating:\n\n- Model configuration with Electric sync\n- Management command usage\n- Admin panel integration\n- API views with sync operations\n- Decorator usage\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/Apoorvgarg-Creator/dj-electric.git\ncd django-electric\n\n# Create virtual environment\npython -m venv venv\nsource venv/bin/activate # On Windows: venv\\Scripts\\activate\n\n# Install in development mode\npip install -e \".[dev]\"\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run with coverage\npytest --cov=django_electric\n\n# Run specific test file\npytest tests/test_client.py\n\n# Run in watch mode\npytest-watch\n```\n\n### Code Quality\n\n```bash\n# Format code\nblack .\nisort .\n\n# Lint\nflake8 django_electric\nmypy django_electric\n\n# Type checking\nmypy django_electric\n```\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes\n4. Add tests for your changes\n5. Ensure all tests pass (`pytest`)\n6. Commit your changes (`git commit -m 'Add amazing feature'`)\n7. Push to the branch (`git push origin feature/amazing-feature`)\n8. Open a Pull Request\n\n## Publishing to PyPI\n\n```bash\n# Build the package\npython -m build\n\n# Upload to PyPI (requires credentials)\ntwine upload dist/*\n```\n\n## Requirements\n\n- Python >= 3.9\n- Django >= 4.2\n- Electric SQL service running\n\n## License\n\nApache License 2.0 - see [LICENSE](LICENSE) for details.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/Apoorvgarg-Creator/dj-electric/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/Apoorvgarg-Creator/dj-electric/discussions)\n- **Documentation**: [Wiki](https://github.com/Apoorvgarg-Creator/dj-electric/wiki)\n\n## Acknowledgments\n\n- Built for [Electric SQL](https://electric-sql.com/)\n- Inspired by local-first and offline-first architectures\n- Thanks to the Django and Electric SQL communities\n\n## Roadmap\n\n- [ ] WebSocket support for real-time updates\n- [ ] Conflict resolution strategies\n- [ ] Multi-tenancy support\n- [ ] GraphQL integration\n- [ ] Django REST Framework integration\n- [ ] Async support with Django 4.2+\n- [ ] Schema migration tools\n- [ ] Performance monitoring and metrics\n\n---\n\nMade with \u2764\ufe0f for the Django and Electric SQL communities\n",
"bugtrack_url": null,
"license": null,
"summary": "Django integration for Electric SQL real-time sync engine",
"version": "0.1.1",
"project_urls": {
"Documentation": "https://github.com/Apoorvgarg-Creator/dj-electric/wiki",
"Homepage": "https://github.com/Apoorvgarg-Creator/dj-electric",
"Issues": "https://github.com/Apoorvgarg-Creator/dj-electric/issues",
"Repository": "https://github.com/Apoorvgarg-Creator/dj-electric"
},
"split_keywords": [
"django",
" electric-sql",
" sync",
" real-time",
" offline-first",
" local-first"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "5fe4ba25fc8bf2086069929a8462bafbf0173b0a5d41d8fd84c0578a25205b0c",
"md5": "c8db84f762962d8fbcb36e61a9458ea0",
"sha256": "ec723f11ebcc145b734c10588c800c1211663446fbbfaf7715fa576cad17a1d1"
},
"downloads": -1,
"filename": "django_electric-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c8db84f762962d8fbcb36e61a9458ea0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 25654,
"upload_time": "2025-10-12T19:15:51",
"upload_time_iso_8601": "2025-10-12T19:15:51.969898Z",
"url": "https://files.pythonhosted.org/packages/5f/e4/ba25fc8bf2086069929a8462bafbf0173b0a5d41d8fd84c0578a25205b0c/django_electric-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "248619cbbc07c8e955c574cd2d36292d97ab54cbfe24bf8ac9038467a722f489",
"md5": "1acd687b93f9f65d94fdca04b0ad4deb",
"sha256": "3c64e4e63e85031491a3099873903deada7f25a76171dfe2b7ea8bf81ed26c18"
},
"downloads": -1,
"filename": "django_electric-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "1acd687b93f9f65d94fdca04b0ad4deb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 26633,
"upload_time": "2025-10-12T19:15:53",
"upload_time_iso_8601": "2025-10-12T19:15:53.146203Z",
"url": "https://files.pythonhosted.org/packages/24/86/19cbbc07c8e955c574cd2d36292d97ab54cbfe24bf8ac9038467a722f489/django_electric-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-12 19:15:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Apoorvgarg-Creator",
"github_project": "dj-electric",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-electric"
}