Skip to content

django-markdownx is a Markdown editor built for Django

License

Notifications You must be signed in to change notification settings

library-collections/django-markdownx

 
 

Repository files navigation

django-markdownx Version

Status Travis Format Python Versions Django Versions License

Key features

  • raw editing
  • live preview
  • drag&drop image uploads (stored locally in MEDIA folder)
  • customizable image insertion tag
  • image filtering using content types and max file size
  • image manipulations (compression, size, cropping, upscaling)
  • pre-&post- text altering
  • easy template customization for layout purposes
  • multiple editors on one page
  • Django Admin support

Preview

Preview

(using Bootstrap for layout and styling)

Menu

Quick Start

  1. Install django-markdownx package.

    pip install django-markdownx
  2. Add markdownx to your INSTALLED_APPS.

    #settings.py
    INSTALLED_APPS = (
        [...]
        'markdownx',
    )
  3. Add url pattern to your urls.py.

    #urls.py
    urlpatterns = [
        [...]
        url(r'^markdownx/', include('markdownx.urls')),
    ]
  4. Collect included markdownx.js and markdownx.css (for django admin styling) to your STATIC_ROOT folder.

    python manage.py collectstatic
  5. ...and don't forget to include jQuery in your html file.

    <head>
        [...]
        <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
    </head>

Usage

Model

#models.py
from markdownx.models import MarkdownxField

class MyModel(models.Model):

    myfield = MarkdownxField()

...and then, include a form's required media in the template using {{ form.media }}:

<form method="POST" action="">{% csrf_token %}
    {{ form }}
</form>
{{ form.media }}

Form

#forms.py
from markdownx.fields import MarkdownxFormField

class MyForm(forms.Form):

    myfield = MarkdownxFormField()

...and then, include a form's required media in the template using {{ form.media }}:

<form method="POST" action="">{% csrf_token %}
    {{ form }}
</form>
{{ form.media }}

Django Admin

When using included MarkdowxModel class in your models, just use MarkdownxModelAdmin as follows:

#admin.py
from django.contrib import admin

from markdownx.admin import MarkdownxModelAdmin

from .models import MyModel

admin.site.register(MyModel, MarkdownxModelAdmin)

However, when you want to use markdownx with other classes – lets say TextField – than override default widget as follows:

#admin.py
from django.db import models
from django.contrib import admin

from markdownx.widgets import AdminMarkdownxWidget

from .models import MyModel

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': AdminMarkdownxWidget},
    }

admin.site.register(MyModel, MyModelAdmin)

Customization

Settings

Place settings in your settings.py to override default values:

#settings.py

# Markdownify
MARKDOWNX_MARKDOWNIFY_FUNCTION = 'markdownx.utils.markdownify' # Default function that compiles markdown using defined extensions. Using custom function can allow you to pre-process or post-process markdown text. See below for more info.

# Markdown extensions
MARKDOWNX_MARKDOWN_EXTENSIONS = [] # List of used markdown extensions. See below for more info.
MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS = {} # Configuration object for used markdown extensions

# Markdown urls
MARKDOWNX_URLS_PATH = '/markdownx/markdownify/' # URL that returns compiled markdown text.
MARKDOWNX_UPLOAD_URLS_PATH = '/markdownx/upload/' # URL that accepts file uploads, returns markdown notation of the image.

# Media path
MARKDOWNX_MEDIA_PATH = 'markdownx/' # Path, where images will be stored in MEDIA_ROOT folder

# Image
MARKDOWNX_UPLOAD_MAX_SIZE = 52428800 # 50MB - maximum file size
MARKDOWNX_UPLOAD_CONTENT_TYPES = ['image/jpeg', 'image/png'] # Acceptable file content types
MARKDOWNX_IMAGE_MAX_SIZE = {'size': (500, 500), 'quality': 90,} # Different options describing final image processing: size, compression etc. See below for more info.

# Editor
MARKDOWNX_EDITOR_RESIZABLE = True # Update editor's height to inner content height while typing

MARKDOWNX_MARKDOWNIFY_FUNCTION

Default function that compiles markdown looks like:

# utils.py
import markdown

from .settings import MARKDOWNX_MARKDOWN_EXTENSIONS, MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS

def markdownify(content):
    return markdown.markdown(content, extensions=MARKDOWNX_MARKDOWN_EXTENSIONS, extension_configs=MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS)

MARKDOWNX_MARKDOWN_EXTENSIONS

#settings.py
MARKDOWNX_MARKDOWN_EXTENSIONS = [
    'markdown.extensions.extra',
    'markdown.extensions.nl2br',
    'markdown.extensions.smarty',
]

Visit https://pythonhosted.org/Markdown/extensions/index.html to read more about markdown extensions.

MARKDOWNX_IMAGE_MAX_SIZE

Dict properties:

  • size – (width, height). When 0 used, i.e.: (500,0), property will figure out proper height by itself
  • quality – default: 90 – image quality, from 0 (full compression) to 100 (no compression)
  • crop – default: False – if True, use size to crop final image
  • upscale – default: False – if image dimensions are smaller than those in size, upscale image to size dimensions

Widget's custom template

Default widget's template looks like:

<div class="markdownx">
    {{ markdownx_editor }}
    <div class="markdownx-preview"></div>
</div>

When you want to use Bootstrap 3 and side-by-side panes (as in preview image above), just place markdownx/widget.html file in your project's 'TEMPLATE_DIRS' folder with:

<div class="markdownx row">
    <div class="col-md-6">
        {{ markdownx_editor }}
    </div>
    <div class="col-md-6">
        <div class="markdownx-preview"></div>
    </div>
</div>

Custom image insertion tag

Markdown uses ![]() syntax to insert uploaded image file. This generates very simple html <image> tag. When you want to have more control and use your own html tags just create custom form_valid() function in ImageUploadView class.

Default ImageUploadView class looks like:

#views.py
from django.http import JsonResponse
from django.views.generic.edit import FormView

from .forms import ImageForm

class ImageUploadView(FormView):

    template_name = "dummy.html"
    form_class = ImageForm
    success_url = '/'

    def form_invalid(self, form):
        response = super(ImageUploadView, self).form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        image_path = form.save()
        response = super(ImageUploadView, self).form_valid(form)

        if self.request.is_ajax():
            image_code = '![]({})'.format(image_path)
            return JsonResponse({'image_code': image_code})
        else:
            return response

JS events

Each markdownx jQuery object triggers two basic events:

  • 'markdownx.init'
  • 'markdownx.update' – also returns 'response' variable containing markdownified text
$('.markdownx').on('markdownx.init', function() {
	console.log("INIT");
});

$('.markdownx').on('markdownx.update', function(e, response) {
	console.log("UPDATE" + response);
});

Dependencies

  • Markdown
  • Pillow
  • Django
  • jQuery

Changelog

v1.6.3
  • Corrupted image upload exception
v1.6.2
  • Runtest template fix
v1.6.1
  • Template render syntax fix
v1.6
  • Support for Django's default_storage
  • Fix for missing MARKDOWNX_MARKDOWNIFY_FUNCTION in settings
v1.5
  • Possibility to customize image insertion code
v1.4.3
  • Markdown abstractable function fix
v1.4.2
  • Maintenance release
v1.4.1
  • Make rendering the markdown abstractable
v1.4
  • Added JS (jQuery) events
  • Custom upload url path
  • Fix when subclassing MarkdownxWidget
v1.3
  • Added Markdown extension configuration setting
v1.2.1
  • Fix by Eduard Sukharev: Fix accessing file length in python3
v1.2
  • Added custom url path setting MARKDOWNX_URLS_PATH to compile markdown with custom view (i.e. for pre/post altering markdown text)
v1.1.3
  • Setup tools fix
v1.1.2
  • Critical fix for image upload
v1.1.1
  • Package fix
v1.1
  • Python 3.3+ support
  • Very simple test added just to test python 3 support
v1.0.1
  • Moved html logic from FormField to Widget to be able to override model objects other than included MarkdownxModel
  • Fixed default value for MARKDOWNX_EDITOR_RESIZABLE
v1.0.0
  • Warning: no backward compatibility
  • Admin, Model and Form custom objects
  • Django admin styles for compiled markdown
  • Settings variables changed:
    • MARKDOWNX_MAX_SIZE => MARKDOWNX_IMAGE_MAX_SIZE
    • MARKDOWNX_MARKDOWN_KWARGS => MARKDOWNX_MARKDOWN_EXTENSIONS
    • MARKDOWNX_MAX_UPLOADSIZE => MARKDOWNX_UPLOAD_MAX_SIZE
    • MARKDOWNX_CONTENT_TYPES => MARKDOWNX_UPLOAD_CONTENT_TYPES
v0.4.2
  • Path fix by argaen
v0.4.1
  • Better editor height updates
  • Refresh preview on image upload
  • Small JS code fixes
v0.4.0
  • editor auto height
v0.3.1
  • JS event fix
v0.3.0
  • version bump
v0.2.9
  • Removed any inlcuded css
  • Removed JS markdown compiler (full python support now with Markdown lib)
v0.2.0
  • Allow to paste tabs using Tab button
v0.1.4
  • package data fix
v0.1.3
  • README.md fix on PyPi
v0.1.2
  • critical setuptools fix
v0.1.1
  • change context name editor to markdownx_editor for better consistency
v0.1.0
  • init

License

django-markdown is licensed under the open source BSD license. Read LICENSE file for details.

Package requests

It would be nice if anyone could support this project by adding missing functionality:

  • tests
  • JS intelligent auto-scrolling when side-by-side panes used

Notes

django-markdownx was inspired by great django-images and django-bootstrap-markdown packages.

About

django-markdownx is a Markdown editor built for Django

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 54.2%
  • JavaScript 28.0%
  • CSS 16.7%
  • HTML 1.1%