Use ReST in Django (and styling docutils with CSS)

Few weeks about I've discovered ReST and I love it. That's the reason why I wanted to use it on this blog - add ability to use ReST in Django admin forms. This guide with small changes can be used to install all these markup languages:

  • html
  • plain
  • markdown
  • restructuredtext
  • textile

Setting up django

To activate ReST in django we'll use django-markupfield which can be installed by using pip:

pip install django-markupfield

It is not necessary to add django-markupfield to INSTALLED_APPS in your settings.py, but you need to add there this:

from docutils.core import publish_parts

def render_rest(markup):
    parts = publish_parts(source=markup, writer_name="html4css1")
    return parts["fragment"]

MARKUP_FIELD_TYPES = (
    ('ReST', render_rest),
)

as you can see on their GitHub page you can use other markup languages. On that page you can also notice that it is necessary to install appropriate renderer in my case docutils (also with pip).

Now you can use MarkupField in your models.py as is in usage section on GitHub. Don`t forget to use South if you haven`t already.

Setting monospace font

If you know markup langauges, you also know It's really handy to type with mono-space font. Here we'll set it for Django admin forms. For that we need to copy basic django base.css. This can be foud in python installed path inside django folder. In my case it was:

<virtualenv>/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css

copy this file inside your static to <static_folder>/admin/css/base.html and find textarea (in my case line 423). There add this tag:

423 textarea {
424     vertical-align: top !important;
425     font-family: monospace;
426 }

or you can even specify exact font. Save and possibly use ./manage.py collectstatic.

Templates

In your templates where you'll render markup text is necessary to add safe tag.

Example:

: Your markufield is called mrkp_body in your models.py and in template you have {{ model.mrkp_body|safe}}

Setting up CSS styles

Now you should be able to get for example bold text in your templates. But what about others tags like code, tables, definitions, lists, etc.? We need to add CSS styles for that. This can be done without touching your current css styles.

For ReST with docutils I have (on this website) these in my style.css for tables, lists, (inline/block) code:

table.docutils
{
}

    table.docutils tbody tr:nth-child(2n+2)
    {
        background: #f4f4f4;
    }

    table.docutils td
    {
        padding: 0.5em 1em 0.5em 1em;
    }

    table.docutils th
    {
        text-align: left;
        font-weight: 700;
        padding: 0.75em 1em 0.75em 1em;
    }

    table.docutils thead
    {
        border-bottom: solid 1px #ddd;
    }

    table.docutils tfoot
    {
        border-top: solid 1px #ddd;
        background: #eee;
    }

    table.docutils tbody
    {
    }

ul.simple
{
    list-style: disc;
    padding-left: 1em;
}

    ul.simple li
    {
        padding-left: 0.5em;
    }

ol.simple, ol.arabic
{
    list-style: decimal;
    padding-left: 1.25em;
}
    ol.simple li
{
    padding-left: 0.25em;
}



tt.docutils.literal {
  border: 1px solid #cacaca;
  line-height: 1.2em;
  font: 12px Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace;
  padding: 2px;
  overflow:auto;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -moz-background-clip: padding;
  -webkit-background-clip: padding-box;
  background-clip: padding-box;
  background-color: #FAFAFB;
  color: #393939;
  margin: 0px;
}

code {
    white-space: nowrap;
    background-color: #eeeeee;
    font-family: monospace;
}

pre {
  border: 1px solid #cacaca;
  line-height: 1.2em;
  font: 12px Monaco,"Courier New","DejaVu Sans Mono","Bitstream Vera Sans Mono",monospace;
  padding: 10px;
  overflow:auto;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -moz-background-clip: padding;
  -webkit-background-clip: padding-box;
  background-clip: padding-box;
  background-color: #FAFAFB;
  color: #393939;
  margin: 0px;
}

ul + pre {
  margin-top: 1em;
}

pre code {white-space: pre;}

pre span.comment {color: #aaa;}

pre.headers {
  margin-bottom: 0;
  border-bottom-width: 0;
  -webkit-border-radius: 3px 3px 0 0;
  -moz-border-radius: 3px 3px 0 0;
  border-radius: 3px 3px 0 0;
  color: #666;
  background-color: #f1f1f1;
  background-image: -moz-linear-gradient(top, #f1f1f1, #e1e1e1); 
  background-image: -ms-linear-gradient(top, #f1f1f1, #e1e1e1); 
  background-image: -o-linear-gradient(top, #f1f1f1, #e1e1e1); 
  background-image: -webkit-gradient(linear, left top, left bottom, from(#f1f1f1), to(#e1e1e1)); 
  background-image: -webkit-linear-gradient(top, #f1f1f1, #e1e1e1); 
  background-image: linear-gradient(top, #f1f1f1, #e1e1e1);
  filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f1f1f1', EndColorStr='#e1e1e1');
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
}

pre.no-response {
  -webkit-border-radius: 3px 3px;
  -moz-border-radius: 3px 3px;
  border-radius: 3px 3px;
  border-bottom: 1px solid #CACACA;
}

pre.headers + pre.highlight {
  -webkit-border-radius: 0 0 3px 3px;
  -moz-border-radius: 0 0 3px 3px;
  border-radius: 0 0 3px 3px;
}

pre.highlight {
  -webkit-border-radius:3px;
  -moz-border-radius:3px;
  border-radius:3px;
  background-color: #FAFAFB;
}

pre.terminal {
  background-color: #444;
  color: #fff;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -moz-background-clip: padding;
  -webkit-background-clip: padding-box;
  background-clip: padding-box;
  border: 2px solid #DEDEDE;
  position: relative;
  padding: 10px;
  text-shadow: none;
  background-image: none;
  filter: none;
}

pre.terminal em {
  color: #f9fe64;
}