A simple custom field for Django that can safely render Markdown and store it in the database.
Project description
django-markdownfield 
A Django field that renders Markdown to sanitized HTML and stores both in your database.
Your text is stored in a MarkdownField. When the model is saved, django-markdownfield renders it
with markdown-it-py (by default),
sanitizes it with nh3, and stores the result in a
RenderedMarkdownField.
The rendering backend is swappable. Bundles EasyMDE (v2.20.0) for admin and frontend forms.
Installation
pip install django-markdownfield
Add to INSTALLED_APPS and configure the rendering backend:
INSTALLED_APPS = [
'markdownfield',
...
'django.contrib.staticfiles',
]
MARKDOWNFIELD_BACKEND = 'markdownfield.backends.markdownit'
Backend configuration (plugins, HTML passthrough, custom backends) is covered in docs/backends.md. A python-markdown backend is also included (pip install django-markdownfield[pymarkdown]).
To enable the admin preview endpoint, add the URL configuration:
urlpatterns = [
path('markdownfield/', include('markdownfield.urls')),
...
]
Quick start
Add a MarkdownField and a paired RenderedMarkdownField to your model:
from django.db import models
from markdownfield.models import MarkdownField, RenderedMarkdownField
from markdownfield.validators import VALIDATOR_STANDARD
class Page(models.Model):
text = MarkdownField(rendered_field='text_rendered', validator=VALIDATOR_STANDARD)
text_rendered = RenderedMarkdownField()
Whenever your model is saved, the RenderedMarkdownField will be updated automatically.
Display in templates
To display the rendered markdown in your template, just display the RenderedMarkdownField like any other field.
{{ page.text_rendered }}
If you don't want to use a RenderedMarkdownField, use the template filter to render raw Markdown in your templates directly:
{% load markdownfield %}
{{ page.text|render_markdown }}
{{ page.text|render_markdown:"classy" }}
The argument is a validator name. Defaults to standard.
Render in Python
from markdownfield.rendering import render_markdown
from markdownfield.validators import VALIDATOR_STANDARD
html = render_markdown('**bold**', VALIDATOR_STANDARD)
Validators
Validators control which HTML tags and attributes survive sanitization, and which toolbar buttons appear in the editor.
| Validator | Tags | Use case |
|---|---|---|
VALIDATOR_STANDARD |
All standard Markdown tags | General content |
VALIDATOR_CLASSY |
Standard + class on links/images, data-* attributes |
Styled content |
VALIDATOR_NO_IMAGES |
Standard without images | User-generated content |
VALIDATOR_BASIC |
Inline only: bold, italic, strikethrough, code, links | Comments, bios |
VALIDATOR_NULL |
No sanitization | Dangerous. Allows XSS. |
Full details + custom validators are covered in docs/validators.md.
Editor
The EasyMDE editor is enabled automatically in admin and frontend ModelForms.
For frontend forms, you will need to include the form media in your template:
<head>
{{ form.media.css }}
</head>
<body>
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Save</button>
</form>
{{ form.media.js }}
</body>
Disable per-field with use_editor=False (frontend) or use_admin_editor=False (admin).
EasyMDE options can be customized by overriding the widget in your form:
from markdownfield.widgets import MDEWidget
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['text']
widgets = {
'text': MDEWidget(options={'toolbar': ['bold', 'italic', 'link']}),
}
Link processing
These settings control post-sanitization link handling. They apply regardless of which backend is used.
| Setting | Default | Description |
|---|---|---|
MARKDOWNFIELD_MARK_EXTERNAL_LINKS |
True |
Add target="_blank" and class="external" to external links. |
MARKDOWNFIELD_INTERNAL_URL |
None |
Your site's URL or a list of URLs (e.g. 'https://example.com' or ['https://example.com', 'https://cdn.example.com']). Links matching these are treated as internal. Without it, all links are treated as external. |
MARKDOWNFIELD_BLOCKED_LINK_DOMAINS |
[] |
List of domains whose links are stripped (link text preserved). |
Management commands
rerender_markdown - re-renders all stored Markdown into their paired rendered fields. Run after upgrading django-markdownfield, changing validators, or switching backends.
python manage.py rerender_markdown
python manage.py rerender_markdown --dry-run
Further reading
- Backends - switching backends, python-markdown support, custom backends, plugins
- Validators - built-in validators, creating custom validators
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_markdownfield-0.19.0.tar.gz.
File metadata
- Download URL: django_markdownfield-0.19.0.tar.gz
- Upload date:
- Size: 186.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8816df001f9b32e7a70b3e6c334f02d61e3203878a1b5186a7ad39fe37978028
|
|
| MD5 |
2d8c1388948ca1cdde9eb95a8be25464
|
|
| BLAKE2b-256 |
d8f045cce1695f567100b2588003e1b2d64cf430cf85854ceb363f13250ee0df
|
Provenance
The following attestation bundles were made for django_markdownfield-0.19.0.tar.gz:
Publisher:
release.yml on dmptrluke/django-markdownfield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_markdownfield-0.19.0.tar.gz -
Subject digest:
8816df001f9b32e7a70b3e6c334f02d61e3203878a1b5186a7ad39fe37978028 - Sigstore transparency entry: 1214725485
- Sigstore integration time:
-
Permalink:
dmptrluke/django-markdownfield@0915278e230ba336dba67e3ab68e7af0bceae42e -
Branch / Tag:
refs/tags/v0.19.0 - Owner: https://github.com/dmptrluke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0915278e230ba336dba67e3ab68e7af0bceae42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_markdownfield-0.19.0-py3-none-any.whl.
File metadata
- Download URL: django_markdownfield-0.19.0-py3-none-any.whl
- Upload date:
- Size: 139.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4713fe5b5b7c7a5d92702a5ca6f45ec7f952e2447d890cab43c01808ac408fb2
|
|
| MD5 |
dd3e6c5c6e1d63dae099c8b272fadd68
|
|
| BLAKE2b-256 |
5d4145340b029500f15dc0690536981b9ec6b6303607f5104f2b76a1d3abfb1c
|
Provenance
The following attestation bundles were made for django_markdownfield-0.19.0-py3-none-any.whl:
Publisher:
release.yml on dmptrluke/django-markdownfield
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_markdownfield-0.19.0-py3-none-any.whl -
Subject digest:
4713fe5b5b7c7a5d92702a5ca6f45ec7f952e2447d890cab43c01808ac408fb2 - Sigstore transparency entry: 1214725542
- Sigstore integration time:
-
Permalink:
dmptrluke/django-markdownfield@0915278e230ba336dba67e3ab68e7af0bceae42e -
Branch / Tag:
refs/tags/v0.19.0 - Owner: https://github.com/dmptrluke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0915278e230ba336dba67e3ab68e7af0bceae42e -
Trigger Event:
push
-
Statement type: