I implemented a syntax highlighted field and want feedback

I achieved what I wanted to do, but I feel like shooting myself in the knee.

What I wanted was to show a syntax highlighted field in the admin:

How I did it:

  1. overwrite change_view in the ModelAdmin
  2. overwrite change_form admin template that catches the data field and wraps a <div id="editor"> around it and has some ace related js
  3. extended admin_base.html and added ace.js to {% block extrahead %} of it
  4. added some js code to change_form admin template

I feel guilty about my js code: I added an eventListener to all of my buttons, so that:

  1. it reads in the value from #editor via getValue()
  2. creates a fake input element with name="data" and puts the received data in it’s value
  3. appends that fake input element to one of the “real” input elements

model:


class Answer(models.Model):
    name = models.CharField("name", max_length = 32)
    data = models.TextField("python code", max_length = 65535)

admin:

class AnswerAdmin(admin.ModelAdmin):
    form = AnswerAdminForm

    def change_view(self, request, object_id, form_url = "", extra_context = None):
        extra_context = extra_context or {}
        if request.method == "GET":
            obj = Answer.objects.get(pk = object_id)
            extra_context["code"] = Answer.objects.get(pk = object_id).data
        return super().change_view(request, object_id, form_url, extra_context = extra_context,)

change_form template:


{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block field_sets %}
    {% for fieldset in adminform %}
        <fieldset class="module aligned {{ fieldset.classes }}">
            {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
            {% if fieldset.description %}
                <div class="description">{{ fieldset.description|safe }}</div>
            {% endif %}
            {% for line in fieldset %}
                <div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
                    {% if line.fields|length == 1 %}{{ line.errors }}{% else %}<div class="flex-container form-multiline">{% endif %}
                    {% for field in line %}
                        {% if "Data:" in field.label_tag %} {# here #}
                            {{ field.label_tag }}<div id="editor">{{ field.field }}</div>
                        {% else %}
                            ...
                        {% endif %}
                    {% endfor %}
                    {% if not line.fields|length == 1 %}</div>{% endif %}
                </div>
            {% endfor %}
        </fieldset>
    {% endfor %}
{% endblock %}

{% block after_field_sets %}
    
    <style type="text/css" media="screen">
        #editor {
                 position: relative;
                 min-width: 660px;
                 max-width: 1680px;
                 width: auto;
                 height: 380px;
                 }
    </style>

    <script>
        var editor = ace.edit("editor");
        editor.setTheme("ace/theme/dracula");
        editor.session.setMode("ace/mode/python");

        document.addEventListener("DOMContentLoaded", function(){
            let editor_value = editor.getValue().trimLeft().trimRight();
            editor.setValue(editor_value);
            editor.clearSelection();
            let inputs = document.querySelectorAll("input[type=submit]");

            let send_data = function() {
                let finput = document.createElement("textarea"); 
                finput.type="text"; 
                finput.name="data", 
                finput.id="id_data"; 
                finput.value=editor.getValue(); 

                let name = document.getElementById("id_name"); 
                name.insertAdjacentElement("beforebegin", finput); 
            }

            inputs.forEach(e => { e.addEventListener("click", () => {send_data()})})
        });
    </script>
{% endblock %}

the form:

class AnswerAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["data"].initial = """class Test:\n    def __init__(self):\n       print("hello")"""
        
     
class Meta:
    model = Answer
    fields = ["name", "data"]

I would like to get some feedback on this approach if possible. Otherwise I hope this code is of some help to someone else in the future :slight_smile:

Hey,
I’m looking to add syntax highlighting for code in my Django project. I came across this project, and it’s impressive work! I have a few suggestions that could enhance it further:

  1. Imagine I have a blog and want to include code snippets in my posts. It would be great if this project could be tailored for that purpose.
  2. Support for multiple languages with automatic language detection based on syntax would be ideal.
  3. It would also be helpful to add a feature that allows users to easily copy code snippets.

Thanks for sharing this!