From 1545e41019e058ad6dad92213f5b28bd2b02c29c Mon Sep 17 00:00:00 2001 From: Alberto Pianon Date: Wed, 5 Dec 2018 09:46:30 +0100 Subject: [PATCH 1/2] moved all js code to a separate script, added support for django admin inlines --- django_admin_json_editor/admin.py | 1 + .../static/django_admin_json_editor/editor.js | 44 ++++++++++++++ .../django_admin_json_editor/editor.html | 30 +--------- example/app/admin.py | 57 ++++++++++++++++++- .../0004_otherjsonmodel_relatedjsonmodel.py | 31 ++++++++++ example/app/models.py | 15 +++++ 6 files changed, 150 insertions(+), 28 deletions(-) create mode 100644 django_admin_json_editor/static/django_admin_json_editor/editor.js create mode 100644 example/app/migrations/0004_otherjsonmodel_relatedjsonmodel.py diff --git a/django_admin_json_editor/admin.py b/django_admin_json_editor/admin.py index 5b1ca87..0c84186 100644 --- a/django_admin_json_editor/admin.py +++ b/django_admin_json_editor/admin.py @@ -58,6 +58,7 @@ def media(self): 'django_admin_json_editor/jquery/jquery.min.js', 'django_admin_json_editor/bootstrap/js/bootstrap.min.js', 'django_admin_json_editor/jsoneditor/jsoneditor.min.js', + 'django_admin_json_editor/editor.js', ] if self._sceditor: css['all'].append('django_admin_json_editor/sceditor/themes/default.min.css') diff --git a/django_admin_json_editor/static/django_admin_json_editor/editor.js b/django_admin_json_editor/static/django_admin_json_editor/editor.js new file mode 100644 index 0000000..7d6ad96 --- /dev/null +++ b/django_admin_json_editor/static/django_admin_json_editor/editor.js @@ -0,0 +1,44 @@ +var editor = {} +var $ = django.jQuery +var enable_json_editor = function(element){ + var id = element.id + if (id.indexOf('__prefix__') === -1) { // activate editor only if it is not an inline template row + var textarea_id = "id_"+element.id.replace('_editor', '') + var schema = JSON.parse(element.getAttribute('data-schema')) + var data = JSON.parse(element.getAttribute('data-data')) + var options = { + theme: "bootstrap3", + iconlib: "fontawesome4", + schema: schema, + }; + editor[id] = new JSONEditor(element, options); + JSONEditor.plugins.sceditor.emoticonsEnabled = element.getAttribute("data-sceditor"); + editor[id].on('change', function () { + var errors = editor[id].validate(); + if (errors.length) { + console.log(errors); + } + else { + var json = editor[id].getValue(); + $('#'+textarea_id)[0].value = JSON.stringify(json); + } + }); + if (data != null) { + editor[id].setValue(data); + } + + } +} + +$(document).ready(function() { + $(document).find("[id$=_editor]").each(function(){ + enable_json_editor(this); + }); +}); + +$(document).on('formset:added', function(event, $row, formsetName) { + $row.find("[id$=_editor]").each(function(){ + enable_json_editor(this); + }); + +}); \ No newline at end of file diff --git a/django_admin_json_editor/templates/django_admin_json_editor/editor.html b/django_admin_json_editor/templates/django_admin_json_editor/editor.html index a1c2529..878a7a1 100644 --- a/django_admin_json_editor/templates/django_admin_json_editor/editor.html +++ b/django_admin_json_editor/templates/django_admin_json_editor/editor.html @@ -1,29 +1,5 @@ -
- - - +
diff --git a/example/app/admin.py b/example/app/admin.py index 9548cac..9001418 100644 --- a/example/app/admin.py +++ b/example/app/admin.py @@ -3,7 +3,7 @@ from django_admin_json_editor import JSONEditorWidget -from .models import JSONModel, ArrayJSONModel, Tag +from .models import JSONModel, ArrayJSONModel, Tag, OtherJSONModel, RelatedJSONModel DATA_SCHEMA = { @@ -31,6 +31,40 @@ 'required': ['text'] } +OTHER_DATA_SCHEMA = { + 'type': 'object', + 'title': 'Data', + 'properties': { + 'other_text': { + 'title': 'Some other text', + 'type': 'string', + 'format': 'textarea', + }, + 'status': { + 'title': 'Status', + 'type': 'boolean', + }, + }, + 'required': ['other_text'] +} + +RELATED_DATA_SCHEMA = { + 'type': 'object', + 'title': 'Data', + 'properties': { + 'related_info': { + 'title': 'Some related info', + 'type': 'string', + 'format': 'textarea', + }, + 'relevant': { + 'title': 'Relevant', + 'type': 'boolean', + }, + }, + 'required': ['related_info'] +} + def dynamic_schema(widget): return { @@ -84,3 +118,24 @@ def get_form(self, request, obj=None, **kwargs): @admin.register(Tag) class TagAdmin(admin.ModelAdmin): pass + + +class RelatedJSONModelStackedInline(admin.StackedInline): + model = RelatedJSONModel + extra = 0 + def get_formset(self, request, obj=None, **kwargs): + widgets = { + 'related_data': JSONEditorWidget(RELATED_DATA_SCHEMA, False), + } + return super().get_formset(request, obj, widgets=widgets, **kwargs) + +@admin.register(OtherJSONModel) +class OtherJSONModelAdmin(admin.ModelAdmin): + inlines = [ RelatedJSONModelStackedInline, ] + def get_form(self, request, obj=None, **kwargs): + widgets = { + 'data': JSONEditorWidget(OTHER_DATA_SCHEMA, collapsed=False), + } + return super().get_form(request, obj, widgets=widgets, **kwargs) + + \ No newline at end of file diff --git a/example/app/migrations/0004_otherjsonmodel_relatedjsonmodel.py b/example/app/migrations/0004_otherjsonmodel_relatedjsonmodel.py new file mode 100644 index 0000000..0bb61ae --- /dev/null +++ b/example/app/migrations/0004_otherjsonmodel_relatedjsonmodel.py @@ -0,0 +1,31 @@ +# Generated by Django 2.1.3 on 2018-12-05 08:44 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0003_tag'), + ] + + operations = [ + migrations.CreateModel( + name='OtherJSONModel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('data', django.contrib.postgres.fields.jsonb.JSONField(default={'other_text': 'some other text', 'status': True})), + ], + ), + migrations.CreateModel( + name='RelatedJSONModel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('related_data', django.contrib.postgres.fields.jsonb.JSONField(default={'related_info': '', 'relevant': False})), + ('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.OtherJSONModel')), + ], + ), + ] diff --git a/example/app/models.py b/example/app/models.py index c69baf9..dd8ff6f 100644 --- a/example/app/models.py +++ b/example/app/models.py @@ -16,3 +16,18 @@ class ArrayJSONModel(models.Model): class Tag(models.Model): name = models.CharField('name', max_length=10) + + +class OtherJSONModel(models.Model): + name = models.CharField(max_length=50) + data = JSONField(default={ + 'other_text': 'some other text', + 'status': True, + }) + +class RelatedJSONModel(models.Model): + parent = models.ForeignKey(OtherJSONModel, on_delete=models.CASCADE) + related_data = JSONField(default={ + 'related_info': '', + 'relevant': False, + }) From 7efe1aa677af197b1159fd8c682136128f619d38 Mon Sep 17 00:00:00 2001 From: Alberto Pianon Date: Wed, 5 Dec 2018 09:59:13 +0100 Subject: [PATCH 2/2] updated README.md --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index f24c168..3f4cd41 100644 --- a/README.md +++ b/README.md @@ -82,3 +82,33 @@ class JSONModelAdmin(admin.ModelAdmin): return form ``` +### Django admin inlines + +JSONEditorWidget may be used also with django admin inlines, +by overriding + +1) the get_formset method of the StackedInline (or TabularInline) class, and + +2) the get_form method of the ModelAdmin class, + +like in the example below. + + +```python +class RelatedJSONModelStackedInline(admin.StackedInline): + model = RelatedJSONModel + def get_formset(self, request, obj=None, **kwargs): + widgets = { + 'related_data': JSONEditorWidget(RELATED_DATA_SCHEMA, False), + } + return super().get_formset(request, obj, widgets=widgets, **kwargs) + +@admin.register(MyJSONModel) +class MyJSONModelAdmin(admin.ModelAdmin): + inlines = [ RelatedJSONModelStackedInline, ] + def get_form(self, request, obj=None, **kwargs): + widgets = { + 'data': JSONEditorWidget(DATA_SCHEMA, collapsed=False), + } + return super().get_form(request, obj, widgets=widgets, **kwargs) +```