Django Visual Editor
A rich text editor for Django with a clean document-style interface, AI assistant, and mobile support.
Features
- Rich text editing — single contenteditable document with persistent toolbar
- Formatting — bold, italic, underline, strikethrough, headings, bullet/numbered lists, blockquote, code block, inline code, links
- HTML source mode — switch between visual and raw HTML editing
- Fullscreen mode — distraction-free writing
- AI assistant — right-side panel with selection editing, "Replace" / "Insert after" actions, and undo snapshots
- Mic dictation — Web Speech API in the AI panel (requires HTTPS)
- Mobile-friendly — responsive toolbar with large touch targets
- Multi-provider AI — OpenAI, Groq, OpenRouter, Yandex GPT, or any OpenAI-compatible API
Installation
pip install django-visual-editor
# With AI support
pip install django-visual-editor[ai]
Setup
Add to settings.py:
INSTALLED_APPS = [
...
'django_visual_editor',
]
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'
Add 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
Usage
Model field (recommended)
from django_visual_editor import VisualEditorField
class BlogPost(models.Model):
title = models.CharField(max_length=200)
content = VisualEditorField()
Widget
from django_visual_editor import VisualEditorWidget
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'content']
widgets = {
'content': VisualEditorWidget(config={'placeholder': 'Start writing...'}),
}
Template
<div>{{ post.content|safe }}</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{{ form.media }}
<button type="submit">Save</button>
</form>
AI Assistant (optional)
VISUAL_EDITOR_AI_CONFIG = {
'enabled': True,
'default_model': 'gpt-4o',
'models': [
{
'id': 'gpt-4o',
'name': 'GPT-4o',
'provider': 'OpenAI',
'model': 'gpt-4o',
'api_key': os.environ.get('OPENAI_API_KEY'),
'base_url': None,
},
{
'id': 'llama',
'name': 'Llama 4 Scout',
'provider': 'OpenRouter',
'model': 'meta-llama/llama-4-scout:free',
'api_key': os.environ.get('OPENROUTER_API_KEY'),
'base_url': 'https://openrouter.ai/api/v1',
},
],
}
Select text in the editor and click ✦ Ask AI to edit the selection. The AI panel shows a preview before applying changes. Use the ↩ button to undo AI edits (up to 10 snapshots).
Development
git clone https://github.com/hvlads/django-visual-editor.git
cd django-visual-editor
pip install -e ".[ai]"
cd frontend
npm install
npm run build
# or: npm run dev (watch mode)
Cleanup images
python manage.py cleanup_editor_images --dry-run
python manage.py cleanup_editor_images
License
MIT
Metadata
Release files for django-visual-editor 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_visual_editor-0.7.0.tar.gz | 30.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_visual_editor-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 61.1 kB
Release files / django_visual_editor-0.7.0.tar.gz
| Download URL | django_visual_editor-0.7.0.tar.gz |
|---|---|
| Size | 30.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8559ff3aedb5ac0de9a34d8afe228166f9a21097eed85e4f74b75447ad20fce7
|
|
BLAKE2b-256 checksum How to use checksums |
0c653e252f8efd95019e1b981efcd3f309ad6a7f7fd69fd70db9904b80b9ab74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / django_visual_editor-0.7.0-py3-none-any.whl
| Download URL | django_visual_editor-0.7.0-py3-none-any.whl |
|---|---|
| Size | 30.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b9ba46a522caa7fce6f632d42a4ed7f35e6be6f9dd0f9c4a8cc3d6d2d50c534
|
|
BLAKE2b-256 checksum How to use checksums |
c255bb1d2202452c7f722dd1e2c91900c47bd4d31b92a5ed85af8a2e8f87b3a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|