Render HTML as-you-type with Django and AJAX

What exactly are we going to do?

In this tutorial, we’ll be building a simple text editor-like application that renders the text as-you-type with Django and AJAX. This will be able to trigger the HTML tags and render them alongside (Words between <h1> and </h1> tags would be bold and large, Words between <i> and </i> would be italic etc…)

Blog Poster

We can do this with plain Django, uh.. But the only problem is that we need to click the submit button or something like that to send the data back to the view.py and then render this back (The page will refresh every time you type a single letter!). This isn’t cool right?… But luckily for us, AJAX (AJAX stands for Asynchronous Javacript and XML) comes for our rescue. We can forget the form submission with this, by this I mean, we can use AJAX to render the text as you type in the textarea/input field without actually submitting the form!

Are you excited? Let’s get started without further due.

Project Setup:

Let’s create a project first:

django-admin startproject html_formatter

Get into the project folder,

cd html_formatter

Let’s now create an app,

django-admin startapp formatter_app
Project structure Image
Your project structure should look like this

First things first!

Make sure your html_formatter/urls.py file looks like this.

from django.contrib import admin               
from django.urls import path, include # Include 'include'
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('formatter_app.urls')) # Add this line!
  ]

Create an urls.py file in your formatter_app directory and add the following lines,

# formatter_app/urls.py       
from django.urls import path     
from . import views                 
urlpatterns = [                
    path('', views.index, name = 'index')       
]

Change the lookup path for Django templates in your html_formatter/settings.py file as
shown below:

import os #import this!
....
....
TEMPLATES = [   
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # Add this line
         ....
         ....
    },       
]

Finally, create a folder named ‘templates’ in the same level where your manage.py file is.

Final project structure
Your project structure should look like this
Ok, Ok.. That’s it for the setup.. Let’s actually get started

In our formatter_app/views.py we need to create a function called index. This is where we’ll be manipulating our app.

Just make sure to paste the following lines in your views.py file, don’t worry if you didn’t get what we’re doing.. I promise I’ll make them clear.

from django.shortcuts import render
from django.http import JsonResponse
def index(request):
    if request.method == "GET":
        return render(request, 'index.html')
    elif request.is_ajax():
        data = request.POST.get('text', None)
        if data:
            response = { 'msg': data }
            return JsonResponse(response)
        else:
            response = { 'msg': "" }
            return JsonResponse(response)

Next, we’ll create an index.html file in our templates folder. And add the below lines :

<!DOCTYPE html> 
<html lang="en">        
<head>       
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Formatter</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>         
</head>        
<body>         
    <div>     
        <form action="" method="post">
            <label for="">Enter Text:</label>
            <br>
            <textarea name="text" id="text_box" cols="50" rows="10"></textarea>
        </form> 
        <span>Result:</span>
        <div style="border:1px solid black; width:420px; height:400px;" id="output">    
        </div>     
    </div>     
    <script>    
        $('#text_box').on('input', function (e) {
            e.preventDefault();
         $.ajax({
            type: "POST",
            url: "{% url 'index' %}",
            data: {
               text: $('#text_box').val(),
               csrfmiddlewaretoken: '{{ csrf_token }}',
               dataType: "json",
            },  
            success: function (data) {
               $('#output').html(data.msg)
            },
            failure: function () {
               $('#output').html('Error Encountered!') 
            }    
         });       
      });              
    </script>        
</body>              
</html>

We’re done! Start the local development server to see how we did so far

python manage.py runserver

You’ll get an output something like this:

Final output
See that? My <h1>Hello World</h1> got rendered!

How is this actually working?

Ok, This is cool. But It’ll be a great deal if you know how this works (of course, you need to understand this right?). Pay attention to the id’s of <textarea></textarea> (id=”text_box“) and <div></div> (id=”output“). We’ve attached an eventlistener for event type input to <textarea></textarea> (with id=”text_box“) . This input event is fired everytime we type something into the textbox and for this all, we’re using a Javascript library called JQuery. This library, built on top of Javascript eases our work by shortening the code we need to write to get things done. To use JQuery in our HTML, just add the below line inside of our <head></head> tag.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

Now, coming to our code, we’ve added e.preventDefault() this prevents the form from submitted in a default way (On pressing Enter key). Next, we’re making an AJAX request. The type of request is POST, and the url to send this request is “{% url ‘index’ %}“. And, after this, we are sending the data in JSON format. This contains text (this holds the text entered into the <textarea></textarea>), csrfmiddlewaretoken (Enables us to send an AJAX POST request everytime we type something) and the lastone is the datatype we’re sending to the server (obviously, JSON).

Thers’s lot to explain! Keep Reading…

This goes and checks our index function in our views.py. And since, the request is and AJAX request, our elif block gets executed. In this block, we’ll collect the data from the JSON sent by AJAX request with the following line:

data = request.POST.get('text', None)

Remember! ‘text‘ is the key for the JSON object where we stored the text entered into the textarea. If we didn’t type a thing, we’ll get None. Now, if our data is not None, we’ll store the data in a dictionary named response with key ‘msg‘. If our data is None, we’ll store an empty string in ‘msg‘. Finally, we’ll return this response dictionary as a JsonResponse back to the AJAX. (The reason we’re sending this as JSON is that Python dictionary isn’t supported in Javascript. So, we’re converting Python dictionary to equivalent JSON).

Now, We sent the data back to AJAX, so our AJAX request is treated to be successful. In this case, the AJAX now executes the success callback function, where we’ll change the content inside the <div></div> with id=”output” to the data we’ve received as JSON from the views.py. That’s it! Your HTML will get rendered.

You’re great! You’ve learned a very useful technique!

With this technique, there’s a vast possibility. You can add CSS, Javascript and what not?.. Make a website something like codepen.io.

Good Luck and happy learning!

Find this code on Github: https://github.com/Chandu-4444/html_formatter