I am working on integrating JSONEditor into the Django admin. There is one field in my model that uses the Postgres JSON and the Tree editor in this library is perfect.
class Executable(models.Model):
""" Simplified model for sake of the question."""
recipe = JSONField(null=True, blank=True)
I've made decent progress (I think) integrating the JSONEditor library within the appropriate create/edit screen in the Django Admin. The data is displayed correctly upon loading but for some reason when I make edits within the JSONEditorWidget the changes are not saved. I'm sure there is some save
override that I need to work on, or that I'm missing something obvious, but I'm really not sure where to go from here.
import json
from django import forms, utils
from django.contrib import admin
from .models import Executable
class JSONEditorWidget(forms.Widget):
html_template = """
<div id='%(name)s_editor_holder'></div>
<script type="text/javascript">
var options = {
"mode": "tree",
"search": true
};
var %(name)s_editor = new JSONEditor(container, options);
var json = %(value)s
%(name)s_editor.set(json);
%(name)s_editor.expandAll();
var json = %(name)s_editor.get(json);
</script>
<textarea readonly class="vLargeTextField" cols="40" id="id_%(name)s" name="%(name)s" rows="2" height="20px">%(value)s</textarea>
"""
def __init__(self, attrs=None, formats=None, defaults=None):
self.formats = formats
self.defaults = defaults
super(JSONEditorWidget, self).__init__(attrs)
def render(self, name, value, attrs=None):
if isinstance(value, basestring): # Edit existing instance
value = json.loads(value)
result = self.html_template % {
'name': name,
'value': json.dumps(value)
}
return utils.safestring.mark_safe(result)
class ExecutableForm(forms.ModelForm):
recipe = forms.CharField(widget=JSONEditorWidget()) # Kwargs here?
class Meta:
model = Executable
fields = '__all__'
class Media:
css = {
'all': ('http://www.jsoneditoronline.org/app.min.css',) # TEMP
}
js = (
'http://www.jsoneditoronline.org/app.min.js', # TEMP
)
class ExecutableAdmin(admin.ModelAdmin):
model = Executable
form = ExecutableForm
fields = (('request', 'status'), 'recipe')
admin.site.register(Executable, ExecutableAdmin)
Django's Admin is amazing. A built-in and fully functional interface that quickly gets in and allows data entry is priceless. Developers can focus on building additional functionality instead of creating dummy interfaces to interact with the database.
Django provides a default admin interface which can be used to perform create, read, update and delete operations on the model directly. It reads set of data that explain and gives information about data from the model, to provide an instant interface where the user can adjust contents of the application .
My solution for Django 1.10.2, jsoneditor#^5.5.9, Postgres 9.5:
models.py
from django.contrib.postgres.fields import JSONField
class Consumer(models.Model):
data = JSONField(default=dict, db_index=True)
admin.py:
from django import forms
from django.contrib import admin
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from .models import Consumer
class JSONEditorWidget(forms.Widget):
template_name = 'jsoneditor.html'
def render(self, name, value, attrs=None):
context = {
'data': value,
'name': name
}
return mark_safe(render_to_string(self.template_name, context))
class ConsumerForm(forms.ModelForm):
class Meta:
model = Consumer
fields = '__all__'
widgets = {
'data': JSONEditorWidget()
}
class Media:
css = { 'all': ('jsoneditor/dist/jsoneditor.min.css',) }
js = ('jsoneditor/dist/jsoneditor.min.js', )
class ConsumerAdmin(admin.ModelAdmin):
list_display = ['pk']
model = Consumer
form = ConsumerForm
admin.site.register(Consumer, ConsumerAdmin)
jsoneditor.html:
<div id="{{ name }}_editor"></div>
<textarea cols="40" id="id_{{ name }}" name="{{ name }}" rows="10" required="" style="display: none">{{ data }}</textarea>
<script>
console.log('jsoneditor.html');
var container = document.getElementById("{{ name }}_editor");
var options = {
modes: ['code', 'tree'],
search: true,
onChange: function () {
var json = editor.get();
document.getElementById("id_{{ name }}").value=JSON.stringify(json);
}
};
var editor = new JSONEditor(container, options);
var json = {{ data|safe }};
editor.set(json);
</script>
Blockquote Written with StackEdit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With