DEV Community

Cover image for How to build an online python code editor using Ace
Agnes
Agnes

Posted on • Originally published at Medium

How to build an online python code editor using Ace

In this article, you will learn how to employ the Ace library and Django framework to develop a sample Python code editor. We will cover the following :

  • Creating and configuring a Django application.
  • Linking the Ace library to your Django app.
  • Your code editor front-end.
  • Your code editor server-side.

Prerequisites

  • A text editor (e.g., Visual Studio Code)
  • Some basic Django framework and JavaScript knowledge.

Creating and configuring the Django project

Step 1: Open the terminal and in your root folder execute the following command.

django-admin startproject codeEditor

Note : Replace _codeEditor_ with the actual name of your app.

Step 2: Next, still in your terminal, navigate to your new project then run the command below to create a new Django app .

python manage.py startapp codeEditorApp

Note : Replace _codeEditorApp_ with the actual name of your app.

Step 3: Next, In the project settings, register your new app in INSTALLED_APPS, as shown below.

Step 4: Navigate to your app and create a new urls.py file.

Step 5: Back in your project, register your apps’ urls.pyin your projects’ urls.pyas shown below.

Step 6: In the app folder, create a new folder names templates

Your new project structure should look like the one shown below:

codeEditor/  
     __init__.py  
     settings.py  
     urls.py  
     wsgi.py  
     asgi.  
codeEditorApp/  
    __init__.py  
    templates  
    admin.py  
    apps.py  
    models.py  
    tests.py  
    urls.py  
    views.py  
manage.py
Enter fullscreen mode Exit fullscreen mode

Step 7: Back in your project,Follow the steps highlighted here to create a virtual environment below.

Creating the code editor front-end

In the templates folder, create a new file named main.htmland add the code below:

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Python Code Editor</title>  

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src/ace.css" type="text/css" media="screen" charset="utf-8">  
    <script src="https://cdn.jsdelivr.net/npm/ace-builds@1.4.12/src/ace.js"></script>  
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>  
    <script type="text/javascript"> var csrftoken = getCookie('csrftoken');  

        function getCookie(name) {  
            var cookieValue = null;  
            if (document.cookie && document.cookie !== '') {  
                var cookies = document.cookie.split(';');  
                for (var i = 0; i < cookies.length; i++) {  
                    var cookie = cookies[i].trim();  
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {  
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));  
                        break;  
                    }  
                }  
            }  
            return cookieValue;  
        }  

        // Function to get the current time of day  
        function getTimeOfDay() {  
            var now = new Date();  
            var hours = now.getHours();  

            if (hours >= 5 && hours < 12) {  
                return "Good morning, ready for some Python?";  
            } else if (hours >= 12 && hours < 18) {  
                return "Good afternoon, ready for some Python?";  
            } else {  
                return "Good evening , ready for some Python?";  
            }  
        }  

        // Set the salutation based on the time of day  
        var salutation = getTimeOfDay();  
        document.addEventListener('DOMContentLoaded', function () {  
            document.getElementById('salutation').innerText = salutation;  
        }); </script>  
    <style> body {  
            font-family: 'Arial', sans-serif;  
            background-color: #f7f7f7;  
            margin: 0;  
            padding: 0;  
            display: flex;  
            flex-direction: column;  
            align-items: center;  
            height: 100vh;  
        }  

        h1, h2, h3 {  
            color: #333;  
            margin-bottom: 10px;  
        }  

        h1{  
            text-decoration: underline;  
            text-decoration-color: #2ecc71;  
        }  

        h2#salutation {  
            font-size: 24px;  
            color: #2ecc71;  
            text-align: center;  
        }  

        #editor {  
            height: 500px;  
            width: 100%;  
            max-width: 600px;  
            margin-bottom: 20px;  
        }  

        button {  
            padding: 10px;  
            font-size: 16px;  
            background-color: #3498db;  
            color: #fff;  
            border: none;  
            cursor: pointer;  
            left:0;  
            padding: 10px;  
            margin-bottom: 10px;  

        }  

        #outputArea {  
            background-color: #ecf0f1;  
            padding: 20px;  
            border-radius: 8px;  
            width: 100%;  
            max-width: 600px;  
        }  

        #output {  
            white-space: pre-wrap;  
        } </style>  
</head>  
<body>  
    <h1>Python Code Editor</h1>  

    <h2 id="salutation"></h2>  

    <div id="editor"></div>  

    <button onclick="runCode()">Run</button>  

    <div id="outputArea">  
        <h3>Output:</h3>  
        <pre id="output"></pre>  
    </div>  

    <script> // Initialize Ace code editor  
        var editor = ace.edit("editor");  
        editor.setTheme("ace/theme/monokai");  
        editor.getSession().setMode("ace/mode/python");  



        editor.setFontSize("16px");  
        // Function to run the code in the Ace editor  
        function runCode() {  
            var code = editor.getValue();  

            // Make an AJAX request to the Django server for code execution  
            $.ajax({  
                type: "POST",  
                url: "/run_code/", // URL of your Django view  
                headers: {  
                    'X-CSRFToken': csrftoken  // Include CSRF token in the request header  
                },  
                data: {  
                    code: code,  
                    language: 'python' // Fixed to Python  
                },  
                success: function(data) {  
                    if (data.result) {  
                        document.getElementById("output").innerText = data.result;  
                    } else {  
                        document.getElementById("output").innerText = data.error;  
                    }  
                },  
                error: function() {  
                    document.getElementById("output").innerText = "Error communicating with the server.";  
                }  
            });  
        } </script>  
</body>  
</html>
Enter fullscreen mode Exit fullscreen mode

The above code starts off with a JavaScript function that handles user salutations , based on the time of the day they are using the editor. Next, there is both CSS and HTML code that handles the Ace code editor structure and styling. We then incorporate a simple JavaScript script which retrieves the Python code from the editor, sends an AJAX (Asynchronous JavaScript and XML) request to the Django server (/run_code/), and handles the server's response. The server response is then displayed in the designated output area (#output) , if the request was successful, or an error is otherwise.

Execute the command below to show what your front-end looks like

python3 manage.py runserver
Enter fullscreen mode Exit fullscreen mode

Your server should display an editor similar to the one below:

Code editor server-side (Django back-end)

To make the above code editor functional, follow the steps below to build its back-end.

Step 1: Inside the apps’ views.py, add the code below

from django.shortcuts import render  
from django.http import JsonResponse  
from django.views.decorators.csrf import csrf_exempt  
import subprocess  


# Create your views here.  
def home(request):  
    return render(request, 'main.html')  


@csrf_exempt   
def run_code(request):  
    if request.method == 'POST':  
        try:  
            code = request.POST.get('code', '')  
            language = request.POST.get('language', '')  

            if language == 'python':  
                result = run_python_code(code)  
                       else:  
                result = "Language not supported for execution."  

            return JsonResponse({'result': result})  

        except Exception as e:  
            return JsonResponse({'error': str(e)})  

    return JsonResponse({'error': 'Invalid request method'})  

# Functions for python code execution  
def run_python_code(code):  
    try:  
        result = subprocess.check_output(['python3', '-c', code], text=True, timeout=5)  
        return result  
    except subprocess.CalledProcessError as e:  
        return f"Error: {e}"  

Enter fullscreen mode Exit fullscreen mode

The above view handles the back-end functionalities by checking whether the code you entered follows Python syntax, then provides the appropriate JsonResponse based on the condition. If the code follows the correct Python syntax, it is then executed and the ouput is displayed in the editor.

Step 2: Next, in the apps’ urls.py, register the url path for the newly created view, as shown below

from django.urls import path  
from . import views  
from django.conf import settings  
from django.conf.urls.static import static  

urlpatterns = [  
    path('', views.home, name='home'),   
    path("run_code/", views.run_code, name='run_code')   

]  

if settings.DEBUG:  
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Enter fullscreen mode Exit fullscreen mode

Note: The same _url_path, (_/run_code/_) , was used in the html template.

Having done all this, your code editor should now be able to properly execute python code.

Top comments (2)

Collapse
 
pawel_p profile image
Pawel Pioro

A very interesting and reasonably simple project!

Collapse
 
kalunda profile image
Agnes

Thank you Pawel.