Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
django-richtextfield
Advanced tools
A Django model field and widget that renders a customizable WYSIWYG/rich text editor
.. image:: https://badge.fury.io/py/django-richtextfield.svg :target: https://pypi.python.org/pypi/django-richtextfield/ :alt: Latest Version
.. image:: https://github.com/jaap3/django-richtextfield/actions/workflows/ci.yml/badge.svg?branch=main :target: https://github.com/jaap3/django-richtextfield/actions/workflows/ci.yml
A Django model field and widget that renders a customizable rich text/WYSIWYG widget.
Works in Django's admin interface and "normal" forms.
Supports global editor settings
, reusable editor profiles
and per field & widget settings
. There's built-in support for
pluggable server side content sanitizers
.
Tested with TinyMCE_ and CKEditor_. Designed to be easily extended to use other editors.
Install django-richtextfield
and add it to your Django
project's INSTALLED_APPS
, django.contrib.admin
must also be in INSTALLED_APPS
::
INSTALLED_APPS = [
'django.contrib.admin',
...
'djrichtextfield'
]
Add the urls to the project's urlpatterns::
path('djrichtextfield/', include('djrichtextfield.urls'))
Configure django-richtextfield
in settings.py
::
DJRICHTEXTFIELD_CONFIG = {
'js': ['//cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js'],
'init_template': 'djrichtextfield/init/tinymce.js',
'settings': {
'menubar': False,
'plugins': 'link image',
'toolbar': 'bold italic | link image | removeformat',
'width': 700
}
}
Now you're ready to use the field in your models::
from djrichtextfield.models import RichTextField
class Post(models.Model):
content = RichTextField()
or forms::
from djrichtextfield.widgets import RichTextWidget
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=RichTextWidget())
When using the editor outside of the admin make sure to include
form.media
in the <head>
of the template::
<head>
...
{{ form.media }}
...
</head>
Define the DJRICHTEXTFIELD_CONFIG
dictionary in your project settings.
This dictionary can have the following keys:
.. _conf_js:
Javascript souce(s) ^^^^^^^^^^^^^^^^^^^
'js'
A list of required javascript files. These can be URLs to a CDN or paths
relative to your STATIC_URL
e.g.::
'js': ['//cdn.ckeditor.com/4.14.0/standard/ckeditor.js']
or::
'js': ['path/to/editor.js', 'path/to/plugin.js']
.. _conf_css:
CSS souce(s) ^^^^^^^^^^^^
'css'
A dictionary of CSS files required.
These can be URLs to a CDN or paths relative to your STATIC_URL
e.g.::
'css': {
'all': [
'https://cdn.example.com/css/editor.css'
]
}
or::
'css': {'all': ['path/to/editor.css', 'path/to/plugin.css']}
.. _conf_init_template:
Editor init template ^^^^^^^^^^^^^^^^^^^^
'init_template'
Path to the init template
_ for your editor. Currently
django-richtextfield
ships with two templates, either::
'init_template': 'djrichtextfield/init/tinymce.js'
or::
'init_template': 'djrichtextfield/init/ckeditor.js'
.. _conf_settings:
Editor settings ^^^^^^^^^^^^^^^
'settings'
A Python dictionary with the default configuration data for your
editor e.g.::
'settings': { # TinyMCE
'menubar': False,
'plugins': 'link image',
'toolbar': 'bold italic | link image | removeformat',
'width': 700
}
or::
'settings': { # CKEditor
'toolbar': [
{'items': ['Format', '-', 'Bold', 'Italic', '-',
'RemoveFormat']},
{'items': ['Link', 'Unlink', 'Image', 'Table']},
{'items': ['Source']}
],
'format_tags': 'p;h1;h2;h3',
'width': 700
}
.. _conf_profiles:
Editor profiles ^^^^^^^^^^^^^^^
'profiles'
This is an optional configuration key. Profiles are "named" custom
settings used to configure specific type of fields. You can configure
profiles like this::
'profiles': {
'basic': {
'toolbar': 'bold italic | removeformat'
},
'advanced': {
'plugins': 'link image table code',
'toolbar': 'formatselect | bold italic | removeformat |'
' link unlink image table | code'
}
}
.. note:: A profile is treated the same way as directly defined
field & widget settings
_. This means that
profile settings are merged with the defaults!
.. _conf_sanitizer:
Content sanitizers ^^^^^^^^^^^^^^^^^^
'sanitizer'
This is an optional configuration key. A sanitizer can be used to
process submitted values before it is returned by the widget. By default no
processing is performed on submitted values. You can configure a sanitizer
either by providing a function or an importable path to a function, like
so::
'sanitizer': lambda value: '<h1>Title</h1>' + value
or::
'sanitizer': 'bleach.clean'
.. _conf_sanitizer_profiles:
'sanitizer_profiles'
This is an optional configuration key. It is possible to override
the default or configured sanitizer for each of the configured profiles
_.
For example to set a custom sanitizer for the advanced
profile::
'sanitizer_profiles': {
'advanced': lambda value: value + 'This text has been sanitized.'
}
You can override the default settings per field::
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=RichTextWidget())
content.widget.field_settings = {'your': 'custom', 'settings': True}
or::
class Post(models.Model):
content = RichTextField(
field_settings={'your': 'custom', 'settings': True},
sanitizer='bleach.linkify'
)
It's recommended to use profiles
_, they make it easier to switch configs
or even editors on a later date. You use a profile like this::
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=RichTextWidget(field_settings='basic'))
or::
class Post(models.Model):
content = RichTextField(field_settings='advanced')
.. note:: Fields always inherit the default settings, customs settings and profiles are merged with the defaults!
It should be fairly easy to use this project with another editor.
All that's required is to configure DJRICHTEXTFIELD_CONFIG
to load the
right Javascript/CSS files and to create a custom init template
_.
For example, to use jQuery based Summernote_ (lite) editor::
DJRICHTEXTFIELD_CONFIG = {
'js': [
'//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js',
'//cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-lite.js',
],
'css': {
'all': [
'//cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-lite.css',
]
},
'init_template': 'path/to/init/summernote.js',
'settings': {
'followingToolbar': False,
'minHeight': 250,
'width': 700,
'toolbar': [
['style', ['bold', 'italic', 'clear']],
],
}
}
Init template ^^^^^^^^^^^^^
The init template is a Django template (so it should be in the template and not in the static directory). It contains a tiny bit of Javascript that's called to initialize each editor. For example, the init template for Summernote would like this::
$('#' + id).summernote(settings)
The init template has the following Javascript variables available from the outer scope:
field
DOM node of the textarea to be replaced
id
The id
attribute of the textarea
default_settings
DJRICHTEXTFIELD_CONFIG['settings']
as a JS object
custom_settings
The field_settings
as a JS object
settings
Merge of default_settings
and custom_settings
django-richtextfield
built to be editor agnostic. This means that it's
up to you to handle file uploads, show content previews and support
other "advanced" features.
.. Profiles: conf_profiles .. _TinyMCE: https://www.tinymce.com/ .. _CKEditor: https://ckeditor.com/ .. _Summernote: https://summernote.org/
1.6.2 (2024-03-07) ^^^^^^^^^^^^^^^^^^
1.6.1 (2021-04-14) ^^^^^^^^^^^^^^^^^^
1.6 (2020-05-20) ^^^^^^^^^^^^^^^^^^
init.js no longer depends on jQuery. This might a backwards incompatible change for:
$e
var. This var has been replaced by field
which is
a plain DOM node instead of a jQuery object.Verified TinyMCE init/config works with TinyMCE 4 and 5
Tested and verified to work with Django 3.1
1.5.0 (2019-12-04) ^^^^^^^^^^^^^^^^^^
1.4.0 (2019-01-31) ^^^^^^^^^^^^^^^^^^
1.3.0 (2018-11-05) ^^^^^^^^^^^^^^^^^^
RichTextWidget
1.2.4 (2018-09-25) ^^^^^^^^^^^^^^^^^^
1.2.3 (2018-09-11) ^^^^^^^^^^^^^^^^^^
1.2.2 (2018-06-12) ^^^^^^^^^^^^^^^^^^
DEBUG
1.2.1 (2018-01-18) ^^^^^^^^^^^^^^^^^^
['admin/js/vendor/jquery/jquery.min.js', 'admin/js/jquery.init.js']
to RichTextWidget.media.js
. This makes the widget usable outside of the
admin (but still requires django.contrib.admin
to be in INSTALLED_APPS
)
and prevents javascript errors inside the admin in certain edge cases.1.2 (2017-12-04) ^^^^^^^^^^^^^^^^
1.1 (2016-01-14) ^^^^^^^^^^^^^^^^
1.0.1 (2014-11-13) ^^^^^^^^^^^^^^^^^^
1.0 (2014-09-30) ^^^^^^^^^^^^^^^^
FAQs
A Django model field and widget that renders a customizable WYSIWYG/rich text editor
We found that django-richtextfield demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.