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: