/django-editorjs-fields

Django plugin for using Editor.js

Primary LanguagePythonMIT LicenseMIT

Editor.js for Django

Django plugin for using Editor.js

This plugin works fine with JSONField in Django >= 3.1

Django Editor.js

Python versions Python versions Downloads

Installation

pip install django-editorjs-fields

Add django_editorjs_fields to INSTALLED_APPS in settings.py for your project:

# settings.py
INSTALLED_APPS = [
    ...
    'django_editorjs_fields',
]

Upgrade

pip install django-editorjs-fields --upgrade
python manage.py collectstatic  # upgrade js and css files

Usage

Add code in your model

# models.py
from django.db import models
from django_editorjs_fields import EditorJsJSONField  # Django >= 3.1
from django_editorjs_fields import EditorJsTextField


class Post(models.Model):
    body_default = models.TextField()
    body_editorjs = EditorJsJSONField()  # Django >= 3.1
    body_editorjs_text = EditorJsTextField()

New in version 0.2.1. Django Templates support

<!-- template.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    {% load editorjs %}
    {{ post.body_default }}
    {{ post.body_editorjs | editorjs}}
    {{ post.body_editorjs_text | editorjs}}
  </body>
</html>

Additionally

You can add custom Editor.js plugins and configs (List plugins)

Example custom field in models.py

# models.py
from django.db import models
from django_editorjs_fields import EditorJsJSONField


class Post(models.Model):
    body_editorjs_custom = EditorJsJSONField(
        plugins=[
            "@editorjs/image",
            "@editorjs/header",
            "editorjs-github-gist-plugin",
            "@editorjs/code@2.6.0",  # version allowed :)
            "@editorjs/list@latest",
            "@editorjs/inline-code",
            "@editorjs/table",
        ],
        tools={
            "Gist": {
                "class": "Gist"  # Include the plugin class. See docs Editor.js plugins
            },
            "Image": {
                "config": {
                    "endpoints": {
                        "byFile": "/editorjs/image_upload/"  # Your custom backend file uploader endpoint
                    }
                }
            }
        },
        i18n={
            'messages': {
                'blockTunes': {
                    "delete": {
                        "Delete": "Удалить"
                    },
                    "moveUp": {
                        "Move up": "Переместить вверх"
                    },
                    "moveDown": {
                        "Move down": "Переместить вниз"
                    }
                }
            },
        }
        null=True,
        blank=True
    )

django-editorjs-fields support this list of Editor.js plugins by default:

EDITORJS_DEFAULT_PLUGINS
EDITORJS_DEFAULT_PLUGINS = (
    '@editorjs/paragraph',
    '@editorjs/image',
    '@editorjs/header',
    '@editorjs/list',
    '@editorjs/checklist',
    '@editorjs/quote',
    '@editorjs/raw',
    '@editorjs/code',
    '@editorjs/inline-code',
    '@editorjs/embed',
    '@editorjs/delimiter',
    '@editorjs/warning',
    '@editorjs/link',
    '@editorjs/marker',
    '@editorjs/table',
)
EDITORJS_DEFAULT_CONFIG_TOOLS
EDITORJS_DEFAULT_CONFIG_TOOLS = {
    'Image': {
        'class': 'ImageTool',
        'inlineToolbar': True,
        "config": {
            "endpoints": {
                "byFile": reverse_lazy('editorjs_image_upload'),
                "byUrl": reverse_lazy('editorjs_image_by_url')
            }
        },
    },
    'Header': {
        'class': 'Header',
        'inlineToolbar': True,
        'config': {
            'placeholder': 'Enter a header',
            'levels': [2, 3, 4],
            'defaultLevel': 2,
        }
    },
    'Checklist': {'class': 'Checklist', 'inlineToolbar': True},
    'List': {'class': 'List', 'inlineToolbar': True},
    'Quote': {'class': 'Quote', 'inlineToolbar': True},
    'Raw': {'class': 'RawTool'},
    'Code': {'class': 'CodeTool'},
    'InlineCode': {'class': 'InlineCode'},
    'Embed': {'class': 'Embed'},
    'Delimiter': {'class': 'Delimiter'},
    'Warning': {'class': 'Warning', 'inlineToolbar': True},
    'LinkTool': {
        'class': 'LinkTool',
        'config': {
            'endpoint': reverse_lazy('editorjs_linktool'),
        }
    },
    'Marker': {'class': 'Marker', 'inlineToolbar': True},
    'Table': {'class': 'Table', 'inlineToolbar': True},
}

EditorJsJSONField accepts all the arguments of JSONField class.

EditorJsTextField accepts all the arguments of TextField class.

Additionally, it includes arguments such as:

Args Description Default
plugins List plugins Editor.js EDITORJS_DEFAULT_PLUGINS
tools Map of Tools to use. Set config tools for Editor.js See docs EDITORJS_DEFAULT_CONFIG_TOOLS
use_editor_js Enables or disables the Editor.js plugin for the field True
autofocus If true, set caret at the first Block after Editor is ready False
hideToolbar If true, toolbar won't be shown False
inlineToolbar Defines default toolbar for all tools. True
readOnly Enable read-only mode False
minHeight Height of Editor's bottom area that allows to set focus on the last Block 300
logLevel Editors log level (how many logs you want to see) ERROR
placeholder First Block placeholder Type text...
defaultBlock This Tool will be used as default. Name should be equal to one of Tool`s keys of passed tools. If not specified, Paragraph Tool will be used paragraph
i18n Internalization config {}
sanitizer Define default sanitizer configuration { p: true, b: true, a: true }

Image uploads

If you want to upload images to the editor then add django_editorjs_fields.urls to urls.py for your project with DEBUG=True:

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

urlpatterns = [
    ...
    path('editorjs/', include('django_editorjs_fields.urls')),
    ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

In production DEBUG=False (use nginx to display images):

# urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    ...
    path('editorjs/', include('django_editorjs_fields.urls')),
    ...
]

See an example of how you can work with the plugin here

Forms

from django import forms
from django_editorjs_fields import EditorJsWidget


class TestForm(forms.ModelForm):
    class Meta:
        model = Post
        exclude = []
        widgets = {
            'body_editorjs': EditorJsWidget(config={'minHeight': 100}),
            'body_editorjs_text': EditorJsWidget(plugins=["@editorjs/image", "@editorjs/header"])
        }

Theme

Default Theme

image

Dark Theme

plugin use css property prefers-color-scheme to define a dark theme in browser

image

Configure

The application can be configured by editing the project's settings.py file.

Key Description Default Type
EDITORJS_DEFAULT_PLUGINS List of plugins names Editor.js from npm See above list[str], tuple[str]
EDITORJS_DEFAULT_CONFIG_TOOLS Map of Tools to use See above dict[str, dict]
EDITORJS_IMAGE_UPLOAD_PATH Path uploads images uploads/images/ str
EDITORJS_IMAGE_UPLOAD_PATH_DATE Subdirectories %Y/%m/ str
EDITORJS_IMAGE_NAME_ORIGINAL To use the original name of the image file? False bool
EDITORJS_IMAGE_NAME Image file name. Ignored when EDITORJS_IMAGE_NAME_ORIGINAL is True token_urlsafe(8) callable(filename: str, file: InMemoryUploadedFile) (docs)
EDITORJS_EMBED_HOSTNAME_ALLOWED List of allowed hostname for embed ('player.vimeo.com','www.youtube.com','coub.com','vine.co','imgur.com','gfycat.com','player.twitch.tv','player.twitch.tv','music.yandex.ru','codepen.io','www.instagram.com','twitframe.com','assets.pinterest.com','www.facebook.com','www.aparat.com'), list[str], tuple[str]
EDITORJS_VERSION Version Editor.js 2.25.0 str

For EDITORJS_IMAGE_NAME was used from secrets import token_urlsafe

Support and updates

Use github issues https://github.com/2ik/django-editorjs-fields/issues