How to Set up TinyMCE in Django

TinyMCE is a WYSIWYG HTML editor. It is used for creating website content.In this tutorial, I will show you how to set up fully working TinyMCE in Django admin and in custom form and how to implement syntax highlighting in frontend with help of it.

Posted by Karan on September 29, 2017   5729 views

 

Introduction

TinyMCE is a WYSIWYG HTML editor, the word WYSIWYG is an acronym for "what you see is what you get". It is designed to simplify website content creation. One can easily copy HTML content and paste into TinyMCE editor, the content you paste will look exactly same, hence WYSIWYG. In this tutorial, we'll implement TinyMCE in Django admin and custom form.

 

Installation

There are many TinyMCE packages available for Django but we will use django-tinymce4-lite

Install it with pip:

pip3 install django-tinymce4-lite

Add "tinymce" to INSTALLED_APPS in settings.py of your project

INSTALLED_APPS = [
      ...
    'tinymce',
      ...
    ]

Add tinymce.urls to urls.py of your project

urlpatterns = [
    ...
    url(r'^tinymce/', include('tinymce.urls')),
    ...
]

Also in settings.py file add following code to configure TinyMCE's toolbars

TINYMCE_DEFAULT_CONFIG = {
    'height': 360,
    'width': 1120,
    'cleanup_on_startup': True,
    'custom_undo_redo_levels': 20,
    'selector': 'textarea',
    'theme': 'modern',
    'plugins': '''
            textcolor save link image media preview codesample contextmenu
            table code lists fullscreen  insertdatetime  nonbreaking
            contextmenu directionality searchreplace wordcount visualblocks
            visualchars code fullscreen autolink lists  charmap print  hr
            anchor pagebreak
            ''',
    'toolbar1': '''
            fullscreen preview bold italic underline | fontselect,
            fontsizeselect  | forecolor backcolor | alignleft alignright |
            aligncenter alignjustify | indent outdent | bullist numlist table |
            | link image media | codesample |
            ''',
    'toolbar2': '''
            visualblocks visualchars |
            charmap hr pagebreak nonbreaking anchor |  code |
            ''',
    'contextmenu': 'formats | link image',
    'menubar': True,
    'statusbar': True,
    }

 

models.py

For brevity, we'll use minimal code required for this tutorial

from django.db import models
from tinymce import HTMLField

class Post(models.Model):
    title = models.CharField(max_length=120)
    description = models.TextField(max_length=250,null=True)
    content = HTMLField('Content')
    draft = models.BooleanField(default=False)

    def __str__(self):
        return self.title

Now we have to register Post model to admin panel, so to do that the admin.py should be like:

from django.contrib import admin

from . import models

admin.site.register(models.Post)

Apply database migration commands if you haven't, then open up admin panel and try adding a Post, TinyMCE should appear in the content field.

 

TinyMCE in modelform

If you want TinyMCE in your modelform then create a file forms.py in the same app and add following code

from django import forms
from tinymce import TinyMCE
from .models import Post


class TinyMCEWidget(TinyMCE):
    def use_required_attribute(self, *args):
        return False


class PostForm(forms.ModelForm):
    content = forms.CharField(
        widget=TinyMCEWidget(
            attrs={'required': False, 'cols': 30, 'rows': 10}
        )
    )

    class Meta:
        model = Post
        fields = '__all__'

And the template corresponding to modelform would be:

{% extends "base.html" %}
{% load static %}

{% block content %}

    {{ form.media }}
    <div class="row form-error">
        <div class="column" id="content">
            <form  method="post" action='' enctype="multipart/form-data">
                {% csrf_token %}
                {{ form.as_p  }}
                <input class="button" type="submit" value="Save">
            </form>
        </div>
    </div>

{% endblock %}

 

JavaScript syntax highlighter

The {} button in TinyMCE editor can be used to add code snippet in the article or content, it provides drop-down to choose language so that it can generate HTML/CSS code as:

<pre class="language-python" style="word-spacing: 0px;">
    <code>pip3 install django-tinymce4-lite</code>
</pre>

To highlight the syntax you need something on the front end which can understand how to highlight code cooked by TinyMCE. So TinyMCE compatible javascript highlighter as prismjs or hightlightjs can be used in the frontend for highlighting code snippets. Being the developer of this blog I have used highlightjs with Github theme for syntax highlighting. You can download either prismjs or highlightjs. After downloading any of them extract the zip and move CSS and JS files to the static directory of your project. After this add these files in the template where you need syntax highlighting, or you may add these file in base template also.

<link href="{% static "styles/github.css" %}" rel="stylesheet">

<script src="{% static "highlight.pack.js" %}"></script>
<script>hljs.initHighlightingOnLoad();</script>

 

Post detail template

Now that we've configured TinyMCE, we need to render the content in post detail page, it can be done by applying safe filter to the content field of article in post detail template as illustrate below

{% extends "base.html" %}
{% load static %}

     {# assuming that your base.html contains block content   #}
     {#   and instance variable being supplied from view      #}


{% block content %}
    
            <h3 > {{instance.title}} </h3>
            <div> {{ instance.content | safe }}  </div>
    
{% endblock %}

 

Setting up filebrowser for media

In production, you need to define STATIC_ROOT and  MEDIA_ROOT in settings.py for getting static files like CSS, JS etc. from third-party packages available to be served, so your project's settings.py should be configured like:

STATIC_URL = '/static/'
MEDIA_URL = '/media/'

STATICFILES_DIRS= [
    os.path.join(BASE_DIR , "static")
]


STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR),"static_cdn")
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR),"media_cdn")

In static_cdn, all the static files from static directories of your project as well as third-party packages will be collected there, and in media_cdn you can use it you collect media objects like images, videos your project. For TinyMCE to store media files we need to create a directory named "uploads" in media_cdn. To upload an image with TinyMCE you can put a link to an image in upload image option, but to upload images or videos we need to install django filebrowser.

pip3 install django-filebrowser-no-grappelli

"django-filebrowser" package needs grappelli to work properly, grappelli is customized Django admin panel which doesn't look appealing at all, so we choose django-filebrowser-no-grappelli package which is compatible with Django's native admin panel as well as other bootstrapped admin panel as jet. For handling images TinyMCE requires pillow package, you can install it with pip

pip3 install pillow

Add filebrowser to INSTALLED_APPS in settings.py

INSTALLED_APPS = [
         ...
    'filebrowser',
         ...
]

Add the following code in urls.py

from filebrowser.sites import site


urlpatterns = [

               ...
    url(r'^admin/', include(admin.site.urls)),
    url(r'^admin/filebrowser/', include(site.urls)),
               ...
]

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL , document_root = settings.STATIC_ROOT )
    urlpatterns += static(settings.MEDIA_URL , document_root = settings.MEDIA_ROOT )

Finally, collect static files to static_cdn with the following command

python3 manage.py collectstatic

# By following the tutorial, your TinyMCE should be ready to help you make awesome content. You can clone and run sample Django project if you have any problem in understanding the tutorial, here is Github link

Happy Coding :)


blog comments powered by Disqus