How to build an online python code editor using Ace
Tags: django, python, codeeditor, webdev
Published: 2024-02-14 19:14:47

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.

![](https://miro.medium.com/v2/resize:fit:350/1*HWcYX-gqsUYke29IYPBWzg.png)



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

**Step 5:**  Back in your project, register your apps’  `urls.py`in your projects’  `urls.py`as shown below.

![](https://miro.medium.com/v2/resize:fit:700/1*rKJvlAuFSvjvJtdYcsLbKw.png)



**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
```

**Step 7:**  Back in your project,Follow the steps highlighted  [here](https://medium.com/@AgnesMbiti/creating-a-python-virtual-environment-on-ubuntu-22-04-5efc173ce655)  to create a virtual environment below.

# Creating the code editor front-end

In the templates folder, create a new file named  `main.html`and 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>
```
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
```
Your server should display an editor similar to the one below:

![](https://miro.medium.com/v2/resize:fit:617/1*cQSbTireFT-AAwVIhZncyA.png)


# 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}"  
  
```
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)
```
_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.