Django Visual Editor: Modern Block‑Based Editing for Django

6 декабря 2025 г.

The Django Visual Editor is a powerful, block‑based visual editor designed specifically for Django projects. It brings a rich, WYSIWYG‑style editing experience to the Django admin and any custom forms, while keeping the output clean and CSS‑free thanks to inline styles. The package is available on PyPI, making installation and updates straightforward.

Why Use Django Visual Editor?

  • Block‑Based Architecture: Six built‑in block types (paragraph, heading H1‑H6, ordered/unordered list, code, quote, image) let authors structure content intuitively.
  • Contextual Toolbar: When a block is selected, a floating toolbar shows only the relevant formatting options.
  • Inline Styles: Text alignment, size, color, bold/italic/underline, and image dimensions are stored directly in the HTML as inline styles—no external CSS required.
  • Image Management: Drag‑and‑drop upload, on‑the‑fly resizing, double‑click replacement, and alignment controls.
  • AI Assistant (optional): Integrated content generation and editing powered by OpenAI, Yandex GPT, or any compatible API.
  • Developer‑Friendly: Full TypeScript source, easy block‑API extension, HTML import/export, and a management command for cleaning unused images.

Installation

Quick start via PyPI

pip install django-visual-editor
# or, with AI support
pip install django-visual-editor[ai]

From source (development)

git clone https://github.com/hvlads/django-visual-editor.git
cd django-visual-editor
pip install -e ".[ai]"          # install Python deps (including AI extras)
cd frontend
npm install
npm run build                    # or npm run dev for hot‑reloading

Configuration in Django

Add the app to INSTALLED_APPS and configure media handling:

# settings.py
INSTALLED_APPS = [
    # …
    'django_visual_editor',
    # …
]

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

Include the editor’s URLs (required for image upload and AI endpoints):

# urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.urls import include, path

urlpatterns = [
    # …
    path('editor/', include('django_visual_editor.urls')),
    # …
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Run migrations to create the image model:

python manage.py migrate

Enabling the AI Assistant (optional)

If you installed the [ai] extra, configure the AI back‑ends in settings.py:

import os

VISUAL_EDITOR_AI_CONFIG = {
    'enabled': True,
    'default_model': 'yandex-gpt',
    'temperature': 0.7,
    'max_tokens': 2000,
    'models': [
        {
            'id': 'yandex-gpt',
            'name': 'YandexGPT',
            'provider': 'Yandex',
            'model': f"gpt://{os.getenv('YANDEX_FOLDER_ID')}/yandexgpt/latest",
            'api_key': os.getenv('YANDEX_API_KEY'),
            'base_url': 'https://llm.api.cloud.yandex.net/v1',
            'project': os.getenv('YANDEX_FOLDER_ID'),
        },
        {
            'id': 'gpt-4o',
            'name': 'GPT‑4o',
            'provider': 'OpenAI',
            'model': 'gpt-4o',
            'api_key': os.getenv('OPENAI_API_KEY'),
            'base_url': None,
            'project': None,
        },
    ],
}

Remember to set the environment variables (e.g., in a .env file):

YANDEX_API_KEY=your‑yandex‑key
YANDEX_FOLDER_ID=your‑folder‑id
OPENAI_API_KEY=sk‑your‑openai‑key

Using the Editor in Your Models

Option 1 – VisualEditorField (recommended)

# models.py
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 your article…',
        }
    )

The field automatically wires the widget into Django admin, ModelForms, and the Django REST Framework (if you expose the field).

Option 2 – Manual widget on a regular TextField

# models.py
from django.db import models

class BlogPost(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()   # plain 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 your article…',
                }
            ),
        }
# admin.py
from django.contrib import admin
from .models import BlogPost
from django import forms
from django_visual_editor import VisualEditorWidget

class BlogPostAdminForm(forms.ModelForm):
    class Meta:
        model = BlogPost
        fields = '__all__'
        widgets = {
            'content': VisualEditorWidget(),
        }

@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
    form = BlogPostAdminForm

Rendering the Content

The editor stores clean HTML with inline styles, so you can safely render it using the safe filter:


{{ post.title }}
{{ post.content|safe }}

Full Form Example (including media assets)



    {% csrf_token %}
    {{ form.as_p }}
    {{ form.media }}   
    Save

Cleaning Up Unused Images

The package provides a management command that scans the media folder and removes images that are no longer referenced in any editor content.

# Dry‑run (shows what would be deleted)
python manage.py cleanup_editor_images --dry-run

# Actual deletion
python manage.py cleanup_editor_images

Schedule this command with cron or a task scheduler to keep your media directory tidy.

Example Project

An example_project is shipped with the repository. To try it locally:

cd example_project
python manage.py migrate
python manage.py createsuperuser   # follow prompts
python manage.py runserver

Then open:

Project Structure Overview

django-visual-editor/
├── django_visual_editor/          # Django app (models, widgets, views, URLs)
│   ├── fields.py
│   ├── widgets.py
│   ├── ai_service.py
│   ├── management/
│   └── static/ & templates/
├── frontend/                     # TypeScript source of the editor
│   ├── src/
│   │   ├── blocks/               # Paragraph, heading, list, etc.
│   │   ├── editor/               # Toolbar, block menu, AI panel
│   │   └── utils/
│   └── webpack.config.js
└── example_project/              # Ready‑to‑run demo

Conclusion

Django Visual Editor fills a niche for developers who need a rich, block‑based editing experience without the overhead of external CSS frameworks. Its inline‑style approach guarantees that the generated HTML looks the same everywhere, and the optional AI assistant can accelerate content creation. Installation is as simple as a pip command, and the API is designed to work out‑of‑the‑box with Django models, forms, and the admin interface.

For the latest updates, detailed documentation, and contribution guidelines, visit the official repository on GitHub and the package page on PyPI.

PREVIOUS ARTICLE
NEXT ARTICLE