Skip to content

dmptrluke/django-markdownfield

Repository files navigation

django-markdownfield PyPI

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.

Editor screenshot

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.

About

A custom field for Django that can safely render Markdown and store it in the database.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors