Block-based visual editor for Django with inline styles, image support and rich formatting
Project description
Django Visual Editor
A modern block-based visual editor for Django with inline styles support. No external CSS required - all styles are embedded directly in HTML.
Features
Block-Based Architecture
- 6 Block Types: Paragraph, Heading (H1-H6), List (ordered/unordered), Code, Quote, Image
- Contextual Toolbar: Appears when a block is selected, showing relevant formatting options
- Add/Remove Blocks: Easy block management with visual controls
- Block Menu: Quick access to all block types
Inline Styles (No CSS Required!)
- Text Alignment: Left, center, right, justify
- Text Size: 5 preset sizes (14px - 24px)
- Text Color: 5 preset colors (gray, blue, green, red, yellow)
- Text Formatting: Bold, italic, underline
- Universal Compatibility: Styles work everywhere without additional CSS files
Image Support
- Upload: Drag-and-drop or file picker
- Resize: Drag the edge to resize images
- Replace: Double-click image to change it
- Alignment: Left, center, right alignment support
- Metadata Storage: Image URL and width stored in block data
AI Assistant (Optional)
- Content Generation: Create new content from AI prompts
- Content Editing: Improve existing blocks with AI assistance
- Context-Aware: Add blocks to context for better AI understanding
- Multi-Provider Support: Works with OpenAI, Yandex GPT, and any OpenAI-compatible API
- Flexible Configuration: Each model has its own API credentials and settings
- Model Switching: Change between different AI models directly in the UI
Developer-Friendly
- TypeScript: Full TypeScript implementation with type safety
- Block API: Easy to extend with custom block types
- HTML Export: Clean HTML with inline styles
- HTML Import: Parse existing HTML with styles extraction
- Auto Cleanup: Management command to remove unused images
Installation
Quick Start (PyPI)
# Install base package
pip install django-visual-editor
# Or install with AI support
pip install django-visual-editor[ai]
From Source (Development)
# Clone repository
git clone https://github.com/hvlads/django-visual-editor.git
cd django-visual-editor
# Install Python dependencies
pip install -e ".[ai]"
# Build frontend
cd frontend
npm install
npm run build
For development with automatic rebuild:
cd frontend
npm run dev
Configure Django
Add to settings.py:
INSTALLED_APPS = [
...
'django_visual_editor',
...
]
# Media files settings
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
Add URL to urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
...
path('editor/', include('django_visual_editor.urls')),
...
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Run Migrations
python manage.py migrate
AI Assistant Setup (Optional)
To enable AI features, configure in settings.py:
import os
VISUAL_EDITOR_AI_CONFIG = {
'enabled': True,
'default_model': 'yandex-gpt', # ID from models list below
# AI Generation Parameters
'temperature': 0.7, # Controls randomness (0.0 - 2.0). Lower = more focused, higher = more creative
'max_tokens': 2000, # Maximum length of generated content
'models': [
{
'id': 'yandex-gpt',
'name': 'YandexGPT',
'provider': 'Yandex',
'model': f"gpt://{os.environ.get('YANDEX_FOLDER_ID')}/yandexgpt/latest",
'api_key': os.environ.get('YANDEX_API_KEY'),
'base_url': 'https://llm.api.cloud.yandex.net/v1',
'project': os.environ.get('YANDEX_FOLDER_ID'),
},
{
'id': 'gpt-4o',
'name': 'GPT-4o',
'provider': 'OpenAI',
'model': 'gpt-4o',
'api_key': os.environ.get('OPENAI_API_KEY'),
'base_url': None, # Uses OpenAI default
'project': None,
},
],
}
Set environment variables in .env:
# Yandex Cloud AI
YANDEX_API_KEY=your-api-key
YANDEX_FOLDER_ID=your-folder-id
# OpenAI (optional)
OPENAI_API_KEY=sk-...
Using the AI Panel
- Click ๐ค button on blocks to add them to context
- Open the AI panel on the right side
- Select a model from the dropdown (or use "Default Model")
- Choose mode: Generate (new content) or Edit (improve existing)
- Enter your prompt and optional instructions
- Click Generate/Apply
Usage
Option 1: Using VisualEditorField (Recommended)
The simplest way - just use the field in your model:
from django.db import models
from django_visual_editor import VisualEditorField
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = VisualEditorField(
config={
'min_height': 400,
'max_height': 800,
'placeholder': 'Start typing...',
}
)
Then use it in forms and admin - no additional configuration needed:
# forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'content']
# Widget is automatically set from the field!
# admin.py
from django.contrib import admin
from .models import BlogPost
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
pass # Widget is automatically set from the field!
Option 2: Using VisualEditorWidget Manually
If you prefer to use a regular TextField and configure the widget in forms:
# models.py
from django.db import models
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = models.TextField() # Regular TextField
# forms.py
from django import forms
from django_visual_editor import VisualEditorWidget
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'content']
widgets = {
'content': VisualEditorWidget(
config={
'min_height': 400,
'max_height': 800,
'placeholder': 'Start typing...',
}
),
}
# admin.py
from django.contrib import admin
from django_visual_editor import VisualEditorWidget
from .models import BlogPost
from django import forms
class BlogPostAdminForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = '__all__'
widgets = {
'content': VisualEditorWidget(),
}
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
form = BlogPostAdminForm
In Templates
<!-- Display content -->
<div class="blog-content">
{{ post.content|safe }}
</div>
<!-- Form -->
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{{ form.media }} <!-- Important! Loads CSS and JS -->
<button type="submit">Save</button>
</form>
Configuration
Available configuration parameters for VisualEditorWidget:
VisualEditorWidget(
config={
'min_height': 300, # Minimum editor height (px)
'max_height': 600, # Maximum editor height (px)
'placeholder': 'Text...', # Placeholder text
}
)
Cleanup Unused Images
Run the management command to remove unused images:
# Show what will be deleted (dry run)
python manage.py cleanup_editor_images --dry-run
# Delete unused images
python manage.py cleanup_editor_images
It's recommended to set up this command in cron for periodic cleanup.
Example Project
Run the example blog:
cd example_project
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Then open:
- http://localhost:8000/ - Post list
- http://localhost:8000/post/new/ - Create new post
- http://localhost:8000/admin/ - Django Admin
Project Structure
django-visual-editor/
โโโ django_visual_editor/ # Django application
โ โโโ models.py # Model for uploaded images
โ โโโ widgets.py # Django widget
โ โโโ fields.py # Custom model field
โ โโโ views.py # Views for image upload and AI assistant
โ โโโ ai_service.py # AI service for content generation
โ โโโ urls.py # URL configuration
โ โโโ management/ # Management commands
โ โโโ static/ # Static files (compiled)
โ โโโ templates/ # Templates
โโโ frontend/ # TypeScript sources
โ โโโ src/
โ โ โโโ blocks/ # Block types (paragraph, heading, list, code, quote, image)
โ โ โโโ editor/ # Block editor, contextual toolbar, block menu, AI panel
โ โ โโโ utils/ # Utils (upload, compression)
โ โ โโโ styles/ # CSS styles (blocks, AI assistant)
โ โโโ package.json
โ โโโ tsconfig.json
โ โโโ webpack.config.js
โโโ example_project/ # Usage example
โโโ blog/ # Demo blog application
Technologies
- Backend: Django 4.2+
- Frontend: TypeScript, Webpack
- Architecture: Block-based editor with inline styles
- Styles: No external CSS required (inline styles)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_visual_editor-0.5.1.tar.gz.
File metadata
- Download URL: django_visual_editor-0.5.1.tar.gz
- Upload date:
- Size: 262.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9a115ecfaac148ff934f02b774a6298c98345f2fe1ba9672856e643cddadb76
|
|
| MD5 |
15479bb910e5f1730975d49d2459f0f3
|
|
| BLAKE2b-256 |
47ed4773c226571b819e18836c8be434d805ab273132207c1bc8a16300d35df2
|
File details
Details for the file django_visual_editor-0.5.1-py3-none-any.whl.
File metadata
- Download URL: django_visual_editor-0.5.1-py3-none-any.whl
- Upload date:
- Size: 261.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56889d9ec1914024d0d927abbc12e6ad2017f70d77c4c539a1988e9098e3363e
|
|
| MD5 |
ad2e530f558ad7527cc5f03424e62fa5
|
|
| BLAKE2b-256 |
fa8189b32ba8a1b7364cc637309adefc0feee2d0aa960b1f4b10ee1d11b559fb
|