Интеграция JsonEditor с Django Admin

Я работаю над интеграцией JSONEditor в панель администратора Django. В моей модели есть одно поле, которое использует Postgres JSON, и редактор дерева в этой библиотеке идеален.

модели.py

class Executable(models.Model):
    """ Simplified model for sake of the question."""

    recipe = JSONField(null=True, blank=True)

Я добился приличного прогресса (я думаю), интегрировав библиотеку JSONEditor в соответствующий экран создания/редактирования в Django Admin. Данные отображаются правильно при загрузке, но по какой-то причине, когда я вношу изменения в JSONEditorWidget, изменения не сохраняются. Я уверен, что есть какое-то переопределение save, над которым мне нужно поработать, или что я упускаю что-то очевидное, но я действительно не уверен, что делать дальше.

admin.py

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)

person Joe Fusaro    schedule 31.05.2016    source источник
comment
@ e4c5 Библиотека хорошо документирована и доступна на Github. Что заставляет вас думать, что это не так? Кстати, я все еще начинающий программист, поэтому, возможно, я что-то упустил :)   -  person Joe Fusaro    schedule 01.06.2016
comment
Извините, я неправильно понял, я не использовал эту библиотеку раньше, но при посещении сайта не было видимых ссылок разработчика или github.   -  person e4c5    schedule 01.06.2016
comment
@ e4c5 не беспокойтесь, ссылка скрыта в нижнем колонтитуле, и я мог видеть, как вы могли прийти к такому выводу. Я обновил ссылку в своем сообщении, чтобы она указывала на репозиторий GitHub, а не на демонстрационный сайт ( github.com/ josdejong/jsoneditor )   -  person Joe Fusaro    schedule 01.06.2016


Ответы (1)


Мое решение для 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>

Блок-цитата Написано с помощью StackEdit.

person sergi0    schedule 30.10.2016
comment
Давно искал что-то подобное... спасибо - person psychok7; 03.04.2017
comment
Извините, но это не сработало для меня идеально. Пришлось добавить мелкие доработки, особенно. преобразование текста json в json var json = JSON.parse({{ data|safe }}); и переименование onChange в change. Ниже приведен обновленный список gist.github.com/rgupta2/761fd987254703673d83426912dc015d. - person comiventor; 10.07.2018