Using rich text editor
SQLAdmin ships with rich text editor (WYSIWYG) fields that you can drop onto
any Text column using the standard form_overrides and form_args
mechanism. The editor's assets are loaded automatically, and a library used by
several fields is only loaded once.
Quick start
from sqladmin import ModelView
from sqladmin.editors import CKEditor5Field
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": CKEditor5Field}
The content field now uses CKEditor 5 on both the create and edit pages.
Configuring an editor
Pass options through form_args, exactly as you would for any other field:
from sqladmin.editors import CKEditor5Field
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": CKEditor5Field}
form_args = {"content": {"min_height": 300}}
Available editors
SQLAdmin includes four editor fields.
CKEditor 5
No API key required.
from sqladmin.editors import CKEditor5Field
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": CKEditor5Field}
form_args = {"content": {"version": "39.0.1", "min_height": 300}}
TinyMCE
Requires a free API key from tiny.cloud.
from sqladmin.editors import TinyMCEField
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": TinyMCEField}
form_args = {
"content": {
"api_key": "your-api-key",
"plugins": "lists link table code",
"toolbar": "bold italic | link | code",
}
}
Quill
No API key required.
from sqladmin.editors import QuillField
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": QuillField}
form_args = {"content": {"theme": "snow"}}
Summernote
No API key required. Built on Bootstrap 4, so it matches the admin interface. Requires jQuery, which is loaded automatically unless you disable it.
from sqladmin.editors import SummernoteField
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": SummernoteField}
form_args = {"content": {"min_height": 300}}
If jQuery is already loaded in your project:
form_args = {"content": {"include_jquery": False}}
Multiple fields
Use different editors on the same form. Each library is loaded only once even when several fields share it:
from sqladmin.editors import CKEditor5Field, TinyMCEField
class PostAdmin(ModelView, model=Post):
form_overrides = {
"content": CKEditor5Field,
"summary": TinyMCEField,
}
form_args = {
"content": {"min_height": 300},
"summary": {"api_key": "your-key"},
}
Pinning a version
Editors load their assets from a CDN, so you can pin whichever version you want:
form_args = {"content": {"version": "43.0.0"}}
How asset loading works
Each editor field exposes a media property listing its CSS and JS URLs.
On the create and edit pages, SQLAdmin merges the media of every field
(deduplicating shared libraries) and injects the CSS in <head> and the JS
before </body>. Each field also renders a small init script that wires the
editor to its textarea.
Writing a custom editor
A rich text editor is just a TextAreaField that declares its assets and an
init template:
from sqladmin.editors import FieldMedia
from wtforms.fields import TextAreaField
class MyEditorField(TextAreaField):
editor_init_template = "myapp/editors/my_editor.html"
def __init__(self, *args, min_height: int = 200, **kwargs):
self.min_height = min_height
super().__init__(*args, **kwargs)
@property
def media(self) -> FieldMedia:
return FieldMedia(
css=["https://example.com/my-editor.css"],
js=["https://example.com/my-editor.js"],
)
The init template receives the field instance as field:
<!-- myapp/editors/my_editor.html -->
<script>
(function () {
var el = document.getElementById("{{ field.id }}");
if (el) {
MyEditor.create(el, { minHeight: {{ field.min_height }} });
}
})();
</script>
Use it like any built-in editor:
class PostAdmin(ModelView, model=Post):
form_overrides = {"content": MyEditorField}