A GitHub-style markdown editor widget for Django forms
Project description
django-markdown-widget
A GitHub-style markdown editor widget for Django forms and admin.
Documentation | PyPI | GitHub
Features
- GitHub-flavored markdown editor with live preview
- Toolbar with common formatting actions (headings, bold, italic, code, tables, etc.)
- Image and file uploads with drag & drop support
- Light, dark, and auto theme support
- Django admin integration via one-line mixin
- Template tag and filter for rendering markdown in templates
- Pluggable renderer and upload handler architecture
- Automatic media cleanup for orphaned uploads
- Management command for bulk orphan detection
- Zero hard dependencies beyond Django (markdown library is optional)
- Keyboard shortcuts (Ctrl+B, Ctrl+I, Ctrl+K, etc.)
Installation
pip install django-markdown-widget
Add to your INSTALLED_APPS and include the URLs:
# settings.py
INSTALLED_APPS = [
...
"django_markdown_widget",
]
# urls.py
from django.urls import include, path
urlpatterns = [
...
path("md-editor/", include("django_markdown_widget.urls")),
]
For server-side rendering, install a markdown library:
pip install markdown
Quick Start
Form Widget
from django.forms import ModelForm
from django_markdown_widget import MarkdownEditorWidget
class PostForm(ModelForm):
class Meta:
model = Post
fields = ["title", "content"]
widgets = {
"content": MarkdownEditorWidget(),
}
Django Admin
from django.contrib import admin
from django_markdown_widget import MarkdownEditorAdminMixin
@admin.register(Post)
class PostAdmin(MarkdownEditorAdminMixin, admin.ModelAdmin):
list_display = ["title", "created_at"]
markdown_fields = ["content"] # omit to apply to all TextFields
Template Rendering
{% load markdown_widget %}
{# As a filter (recommended) #}
{{ post.content|markdown }}
{# As a tag #}
{% markdown post.content %}
Media Cleanup
from django_markdown_widget import MarkdownCleanupMixin
class Post(MarkdownCleanupMixin, models.Model):
content = models.TextField()
# markdown_cleanup_fields = ["content"] # optional: limit to specific fields
Enable in settings:
MD_EDITOR = {
"CLEANUP_MEDIA": True,
}
Bulk cleanup via management command:
python manage.py cleanup_markdown_media --dry-run
python manage.py cleanup_markdown_media
Configuration
All settings are optional and go under MD_EDITOR in your Django settings:
MD_EDITOR = {
# Pluggable backend classes
"RENDERER_CLASS": "django_markdown_widget.renderers.DefaultRenderer",
"UPLOAD_HANDLER_CLASS": "django_markdown_widget.uploads.DefaultUploadHandler",
# Toolbar buttons
"TOOLBAR": [
"heading", "bold", "italic", "strikethrough", "separator",
"quote", "code", "code-block", "link", "image", "separator",
"ordered-list", "unordered-list", "task-list", "separator",
"horizontal-rule", "table", "details", "separator",
"highlight", "superscript", "subscript", "separator",
"attach", "mention", "ref", "separator",
"undo", "redo", "fullscreen",
],
# Upload settings
"ALLOWED_UPLOAD_TYPES": ["image/png", "image/jpeg", "image/gif", "image/webp"],
"MAX_UPLOAD_SIZE": 10 * 1024 * 1024, # 10 MB
"UPLOAD_PATH": "md-editor/uploads/%Y/%m/",
# Editor defaults
"DEFAULT_HEIGHT": "300px",
"PLACEHOLDER": "Add your comment here...",
"THEME": "auto", # "light", "dark", or "auto"
# Security
"REQUIRE_AUTH": True,
# Media cleanup
"CLEANUP_MEDIA": False,
}
Custom Renderer
from django_markdown_widget import BaseRenderer
class MyRenderer(BaseRenderer):
def render(self, markdown_text: str) -> str:
import markdown_it
md = markdown_it.MarkdownIt()
return md.render(markdown_text)
MD_EDITOR = {
"RENDERER_CLASS": "myapp.renderers.MyRenderer",
}
Custom Upload Handler
from django_markdown_widget import BaseUploadHandler
class S3UploadHandler(BaseUploadHandler):
def validate(self, file):
# your validation logic
pass
def save(self, file) -> str:
# save to S3 and return the URL
return url
MD_EDITOR = {
"UPLOAD_HANDLER_CLASS": "myapp.uploads.S3UploadHandler",
}
Development
git clone https://github.com/ganiyevuz/django-md-editor.git
cd django-md-editor
uv sync --group dev
make test
make lint
Run the example app:
cd example
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
License
MIT License. See LICENSE for details.
Project details
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_markdown_widget-1.0.1.tar.gz.
File metadata
- Download URL: django_markdown_widget-1.0.1.tar.gz
- Upload date:
- Size: 101.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da217f033872feda7aed7147e3f9d738719b1966cddfd58ad37cfcf1b4fa3f02
|
|
| MD5 |
4867d4c6553c50aaf95f608d26392be7
|
|
| BLAKE2b-256 |
cf7c8c0ea327b7e43c723c0d41219871a38c71aa5a6315f2266af059356864d5
|
File details
Details for the file django_markdown_widget-1.0.1-py3-none-any.whl.
File metadata
- Download URL: django_markdown_widget-1.0.1-py3-none-any.whl
- Upload date:
- Size: 37.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
749aed0e93d65c3902e23319f752cf79b0d5d3fcb2b677efa6fc2327c9cf8e7a
|
|
| MD5 |
b6135b4090e1ba32eccca595ae0009c3
|
|
| BLAKE2b-256 |
328e72dab0c0e23fbf1860013124a2c37351c0e71a83868e64436e9c13a5636c
|