# Add a utility to render the markdown
from markdown import markdown

def markdownify(content):
    return markdown(
        content,
        [
            'markdown.extensions.fenced_code',
            'codehilite',
        ],
    )

# add the view to somewhere
from django.http import HttpResponse
from django.utils.safestring import mark_safe
from django.views import View
from somewhere.utils import markdownify

class MarkdownifyView(View):
    def post(self, request, *args, **kwargs):
        markdown = markdownify(request.POST['content'])
        return HttpResponse(mark_safe(markdown))

# and the url
urlpatterns = [
    ...
    url(r'^markdownify/$', MarkdownifyView.as_view(), name='markdownify'),
]

# The Textblock looks like
from django.urls import reverse
from django.utils.safestring import mark_safe
from wagtail.wagtailcore import blocks
from somewhere.utils import markdownify

class MarkDownBlock(blocks.TextBlock):
    """ MarkDown Block """

    class Meta:
        icon = 'code'

    def render_basic(self, value, context=None):
        md = markdownify(value)
        return mark_safe(md)

    def render_form(self, value, prefix='', errors=None):
        content = super(MarkDownBlock, self).render_form(value, prefix, errors)
        url = reverse('markdownify')
        return mark_safe("""
        <div class="markdown" data-url="{url}">
            {content}
            <div class="markdown-preview field-content"></div>
        </div>
        <script>$('#{prefix}').closest('.markdown').markdown();</script>
        """.format(content=content, prefix=prefix, url=url))

# And a javascript file to handle live reload in the preview (static/js/markdown.js)
(function ($) {
    $.fn.markdown = function() {

        return this.each( function() {

            var getMarkdown = function() {
                var form = new FormData();
                form.append('content', markdownEditor.val());
                form.append('csrfmiddlewaretoken', getCookie());
                $.ajax({
                    type: 'POST',
                    url: markdown.data('url'),
                    data: form,
                    processData: false,
                    contentType: false,

                    success: function(response) {
                        markdownPreview.html(response);
                        markdown.trigger('markdown.update', [response]);
                    },

                    error: function(response) {
                        console.log("error", response);
                        markdown.trigger('markdown.update_error', [response]);
                    }
                });
            };

            var getCookie = function() {
                return $('[name=csrfmiddlewaretoken]').val();
            };

            var timeout;

            var markdownify = function() {
                clearTimeout(timeout);
                timeout = setTimeout(getMarkdown, 500);
            };

            // events
            var onKeyDownEvent = function(e) {
                if (e.keyCode === 9) { // Tab
                    var start = this.selectionStart;
                    var end = this.selectionEnd;

                    $(this).val($(this).val().substring(0, start) + "\t" + $(this).val().substring(end));
                    this.selectionStart = this.selectionEnd = start + 1;

                    markdownify();

                    return false;
                }
            };

            var onInputChangeEvent = function() {
                markdownify();
            };

            // initialize
            var markdown = $(this);
            var markdownEditor = $(this).find('textarea');
            var markdownPreview = $(this).find('.markdown-preview');

            markdownEditor.on('keydown.markdown', onKeyDownEvent);
            markdownEditor.on('input.markdown propertychange.markdown', onInputChangeEvent);

            markdown.trigger('markdown.init');

            markdownify();
        });
    };

})(jQuery);

# finally link the js file into the cms admin site (wagtail_hooks.py in the root of an app)
from django.contrib.staticfiles.templatetags.staticfiles import static
from django.utils.html import format_html
from wagtail.wagtailcore import hooks

@hooks.register('insert_editor_js')
def editor_js():
    return format_html(
        '<script type="text/javascript" src="{}">',
        static('js/markdown.js')
    )