How I Created a Blog Application Using Django – Part 4

5/5 - (2 votes)

In this fourth part series of our project tutorial on creating a blog application using the Django framework, we will learn how to integrate a rich text editor into our blog application.

If this is your first time attempting this project, you will benefit greatly if you start from the beginning all through the previous part before going through this series.

💡 A rich text editor is a what-you-see-is-what-you-get (WYSIWYG) HTML editor that makes it possible to easily create and publish content on the web. Many rich text editors can be integrated into Django applications.

These include:
👉 TinyMCE
👉 Quill
👉 CKEditor
👉 Summernote
👉 Froala Editor

In this blog project tutorial, you will learn how to integrate and use CKEditor.

CKEditor is a tool with lots of advanced features for text editing including styling options, adding images, links and other components. Like other rich text editors, CKEditor makes it possible to format and display your content in the browser without having any knowledge of web development.

If you have gone through the project on how I demonstrated how to turn a given text into an HTML, integrating CKEditor into our blog application should feel familiar. However, we are in for more advanced stuff than what we did in that project. So, let’s start from scratch to integrate the CKEditor.

Installing and Configuring CKEditor

Run the following on your terminal to install CKEditor.

pip install django-ckeditor

Then add ckeditor in the INSTALLED_APP section of the settings.py file.

INSTALLED_APPS = [
    …
    # custom app
    'blog',
    # third-party apps
    'crispy_forms',
    'crispy_bootstrap4',
    'ckeditor', #add these
]

Next, we will adjust the body field of the Post model to use CKEditor. We can choose to use the provided RichTextField or RichTextUploadingField on our model. The latter has all the features of the former plus file uploading features.

Since we will like to upload images to our blog post, let’s use the latter. In your models.py file, import the RichTextUploadingField. Then, replace the TextField with it.

from ckeditor_uploader.fields import RichTextUploadingField

class Post(models.Model):
   …
   body = RichTextUploadingField()
   …

Let us now configure the CKEditor before running migrations. Go to the settings.py file. Make these adjustments if you haven’t done so.

STATIC_URL = 'static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

Add these to configure where uploaded image files will be stored.

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = 'media/'

Then, add the CKEditor configurations, preferably before the TEMPLATES section.

CKEDITOR_UPLOAD_PATH = 'uploads/'
CKEDITOR_IMAGE_BACKEND = 'pillow'
CKEDITOR_JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'

CKEDITOR_CONFIGS = {
    'default':
       {
            'toolbar': 'full',
            'width': 'auto',
            'extraPlugins': ','.join([
                 'codesnippet',
            ]),
       },
}

The configurations tell Django where to store uploaded images. Since we have already configured the media root, Django will create the media folder, and inside it, the uploads folder, to store uploaded images.

For a detailed explanation of these and other configurations, check this GitHub page and the documentation.

Whenever an image is used in a Django application, it requires the installation of Pillow. Install it and create a requirements.txt file to keep a record of all the modules used in this project if you have not already done so.

Next, proceed to the project-level URLs. Update it to be like this:

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
    path('ckeditor/', include('ckeditor_uploader.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

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

This points to the path to static and media files. The ckeditor_uploader is an app of its own that comes together with the CKEditor module. So, we have to add it to the urls.py. It is from the module we import the RichTextUploadingField class.

Let us now migrate the models file to reflect the changes we have made.

python3 manage.py makemigrations
python3 manage.py migrate

Start the local server and go to the admin interface.

Can you see the CKEditor tool? With this, you can now format your articles and upload images.

Creating a form for the CKEditor

What if we don’t want to access the CKEditor from the admin panel? We can integrate it in a form. Hoping that you have your forms.py file created from the previous series, add this after the CommentForm class.

from ckeditor_uploader.widgets import CKEditorUploadingWidget


class BlogForm(forms.ModelForm):
    body = forms.CharField(widget=CKEditorUploadingWidget())

    class Meta:
        model = Post
        fields = '__all__'

The form will display all fields in the database model. Be sure to import the Post model. Let’s now create the view function.

from django.http import HttpResponse

def CreateBlogPost(request):
    if request.method == 'POST':
        form = BlogForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponse('New blog successfully added!')
    else:
        form = BlogForm()
        context = {
            'form': form
        }
    return render(request, 'create_blog.html', context)

If the request method is POST, we retrieve the data and save it. The data is the input from the user. Then we use HttpResponse to display a confirmation text. Otherwise, we display an empty form.

Next is the endpoints. Go to the app-level URLs and add this:

path('ckeditor/new_post/', CreateBlogPost, name='create'),

Don’t forget to import the view function. Finally, the templates. Create a create_blog.html inside the templates folder and add this:

{% extends "base.html" %}
{% block content %}


<form method="post">
   {% csrf_token %}
   {{ form.as_p }}
   {{ form.media }}

  <input type="submit" value="Submit">
</form>
{% endblock %}

Using crispy form may not be necessary in this case. Now start the local server and go to http://127.0.0.1:8000/ckeditor/new_post/ to see the CKEditor integrated into the form.

You may choose to align the form to the center. To upload images, go to the icon (the eight from the second row by the right). Click on it and click the upload section.

Once you upload images, it will be stored in the media folder.

Conclusion

In this series, we integrated a CKEditor into our blog application. Now, we can easily format our blog posts as well as add images. As always, you can check the source code on my GitHub page.

What are we looking forward to in the next series of this blog project tutorial?

There are more features to add: pagination, sitemap, RSS feeds (if possible), user authentication, performing CRUD operations without using the admin panel, displaying reading time, using a database other than the default sqlite3 and deploying to a production server other than PythonAnywhere.

I see this project spanning up to ten series. Well, that’s under probability. For now, we have to call it a day. Congratulations! You are gradually becoming an intermediate Django developer. Make sure you grab a coffee and give yourself a good treat. You deserved it! See you in the next series.