Your average programmer.
- I (irregularly) post programming tutorials on my blog.
- I'm active on Stack Overflow as user xyres.
Life is short and hard like a bodybuilding elf. — Jimmy Pop.
A better, user-friendly JSON editing form field for Django admin. Also supports Postgres ArrayField.
Home Page: https://django-jsonform.rtfd.io
License: BSD 3-Clause "New" or "Revised" License
Your average programmer.
Life is short and hard like a bodybuilding elf. — Jimmy Pop.
This would allow us to dynamically return the choices
such as objects from the database.
This would also allow us to return a schema based on user permissions.
Hi there,
This is something I was looking for a while.
This app has huge potential, thank you for creating it!
There was a few issue though I came across immediately when I tried.
I had to install psycopg2 in order to able to use django_jsonform.models.fields.JSONField. I got the ‘No module named 'psycopg2'’ error when I tried to run makemigrations.
Django’s built in collapsable fieldsets stopped working after this field type has been added to my model. Any custom fieldset classes are splitted up by spaces when it’s rendered when JSONField is present.
I could fix this issue by wrapping my custom classes into an additional list.
'classes': (['collapse’]) # instead of 'classes': ('collapse')
https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets
Otherwise very good job. I’ll use this app on my website since the next update.
Thanks!
There are some searches in the docs related to the JS errors (when schema and data mismatch, etc.)
Add a page in the docs to explain the errors.
This is useful for manually editing json data.
Currently trying to use a translated lazy string as a "title", produces an error in v2.6.0:
TypeError: Object of type __proxy__ is not JSON serializable
Example schema:
from django.utils.translation import gettext_lazy as _
{
'type': 'object',
'keys': {
'show': {
'type': 'boolean',
'title': _('Show')
},
},
}
with whitenoise environment
manage.py collectstatic
after this command, error pops up.
whitenoise.storage.MissingFileError: The file 'django_jsonform/local/react-json-form.js.map' could not be found with <whitenoise.storage.CompressedManifestStaticFilesStorage object at 0x112204fd0>.
The JS file 'django_jsonform/local/react-json-form.js' references a file which could not be found:
django_jsonform/local/react-json-form.js.map
thanks in advance.
datetime is stored as an ISO string in the json object. Since it's a string, Django's date
filter doesn't work on it in the templates.
It would be better if there were a template filter which would convert the string datetime to a Python's actual datetime
object.
Perhaps something like these:
parse_datetime
: for parsing datetime and date stringparse_time
: for parsing time stringIt works exactly the same as choices
keyword. So it can be an alias.
Probably codepen embeds.
The current check works only for Django 3.xxx:
django.VERSION[0] >= 3 and django.VERSION[1] >= 1:
Recently a new Django version was released 4.0..., with the old check the package is not working because of: django.VERSION[1] >= 1
This will be useful in cases where there are dedicated apps for managing media files or to avoid re-uploading files.
A user will click on the file input, but a modal will open, then a request will be sent to the server and the server will return a list of all the available files for selecting. The user can then choose a file. The path of the file will be saved in the JSON data.
A basic feature would be to add the format to the string type returned by datetime.datetime.isoformat()
This would require a datetime picker in the admin.
A more advanced way to do it would be to allow custom datetime formats, like "YYYY-MM-DD HH:MM", but this is more complicated and with the basic feature anybody could extend the field and format the datetime into their desired format
I love the package, btw!.
When uploading a file but then clearing it, the file's value is removed from the JSON data but the input will still show the selected file.
Creating a form using this schema:
DEFAULT_PARAMETERS_SCHEMA = {
"type": "object",
"properties": {
"max_weekday_characteristics": {
"type": "array",
"items": {
"type": "object",
"properties": {},
"additionalProperties": {
"type": "integer",
"helpText": "Key is a tag-name. Value is the maximum for that tag",
},
},
"minItems": 7,
"maxItems": 7,
"default": [{}, {}, {}, {}, {}, {}, {}],
"title": "Maximum Characteristics per Weekday",
},
},
}
has unexpected behaviour. I would expect that the default form would look like this:
but it instead defaults to being an empty list. I think this is a bug, but please advise.
Hi @bhch
I have a form displaying the following address information. The state choices is filled based on country through jQuery.
The problem is, the address object in DB is empty i.e. {country:"",state:""}.
Am i missing something?
django version: 3.2
using jazzmin for the dashboard UI
ADDRESS={
"type": "dict",
"keys": {
"country": {
"type": "string",
'choices': ['India','China',....]
},
"state": {
"type": "string",
'choices': []
}
}
}
//models.js
address = JSONField(schema=ADDRESS)
The value is saved in the db, but not displayed in select input after saving the object.
At least doesn't work inside a dict. Possibly also affects array as well.
We have a field that is like this:
action_timestamps = JSONField(
default=dict,
schema={
'type': 'object',
'keys': {
'timestamp_1': {
'type': 'string',
},
'timestamp_2': {
'type': 'string',
},
}
},
)
Outside of the admin, we set the timestamps only when they are needed.
So for example this could be a valid value for us:
{
"timestamp_1": "2018-11-19 12:10:02.353829"
}
However, once you edit the model from the admin, that value is set to:
{
"timestamp_1": "2018-11-19 12:10:02.353829",
"timestamp_2": ""
}
Would it be possible to add a keyword to the schema key that makes so the key isn't stored unless it has a non falsy value?
Currently only one handler can be specified in the settings. This pattern poses problems if a third party app also has a handler.
Passing an upload handler function to the JSONField
or the widget will allow different apps or models to use different upload handler functions.
The url registration is optional and is only required for file uploads. Therefore this exception should not be raised if django_jsonform's url isn't registered.
weekend_days = JSONField(schema={
"type": "dict",
"keys": {
"monday": {
"type": "number",
"default": 0
},
"tuesday": {
"type": "number",
"default": 0
}
}
} )
I use Django 4.1, Django json form 2.10.1
. So, when I run the above as a model field in Django, instead of setting 0 as default
value for keys Monday, Tuesday, the Django-jsonform
sets Null
as the value which is not expected
It's gets frustrating when first or last items are moved up or down and the hidden buttons reappear which affects the position of previously visible button.
Disable the buttons instead of hiding them.
Using choices in an array will show the already selected choice again. Provide a way to keep selected items unique and only show unselected options.
If I try to add a new related object that has a jsonform through an inline it doesn't save the options.
If I edit it works as expected.
models.py:
from django.db import models
from django_jsonform.models.fields import JSONField
PREF_SCHEMA = {
"type": "dict",
"keys": {
"periodTime": {
"title": "Time of day",
"type": "dict",
"keys": {
"morning": {
"type": "boolean",
"title": "Morning",
},
"afternoon": {
"type": "boolean",
"title": "Afternoon",
},
"evening": {
"type": "boolean",
"title": "Evening",
},
},
},
},
}
class MyModel(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
class MyRelatedModel(models.Model):
pref = JSONField(schema=PREF_SCHEMA)
mymodel = models.ForeignKey(MyModel, on_delete=models.CASCADE)
admin.py:
from django.contrib import admin
from django import forms
from .models import MyModel
from .models import MyRelatedModel
class MyRelatedModelForm(forms.ModelForm):
class Meta:
model = MyRelatedModel
fields = ("pref",)
class MyRelatedModelInline(admin.TabularInline):
model = MyRelatedModel
form = MyRelatedModelForm
extra = 0
can_delete = True
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
inlines = (MyRelatedModelInline,)
@admin.register(MyRelatedModel)
class MyRelatedModelAdmin(admin.ModelAdmin):
pass
Here is a full project with that issue happening:
One of the very useful features in JSON Schemas is the option to have multiple options via allOf/anyOf/oneOf
for the same key/set of keys when nesting. For our project github.com/cividi/spatial-data-package-platform this would solve a major hurdle for fully embracing django-jsonform as an elegant solution for tenant defined forms. Would be awesome to know if this is at all thinkable as a future addition. Thanks so much for your efforts.
Hi,
I've been using this package due to the very friendly UI on the admin page + it substitutes the ArrayField which would crash all my sqlite3 unit tests (my actual DB is PostgreSQL).
However, I noticed that once I add a 'default=dict', or any callable for that matter, then the dropdown no longer works on django admin: clicking the '+' does nothing.
Is this a bug? If not, could you provide me an example of how to specify a default value in my model for the JSONField?
Thanks!
Hello! Thanks for sharing awesome library!
I came up with idea of extending the library to support foreign key id property field and select id using django's default autocomplete_field UI.
For example,
json schema would be like
{
'$schema': 'http://json-schema.org/schema#',
'type': 'array',
'items': {
'type': 'object',
'required': [
"model_id", "field"
],
'properties': {
'model_id': { -> foreign key id, maybe type should be `ExampleModel` or something else.
'title': 'entity',
'type': 'number',
},
'field': {
'title': 'field',
'type': 'string',
}
}
}
}
where there exists django model named ExampleModel.
class ExampleModel(models.Model):
entity_field = models.CharField(max_length=32)
This feature might empower the functionalities of your cool library!
Thanks.
django-jsonform version: 2.10.1
django version: 3.2.14
I have this model field which is an array imported from django_jsonform.models.fields, I would like it to be shown in the admin panel as a multiselector of another model, a kind of Foreign Key where, however, I go to save only the ids of the selected models.
In my admin form I first tried to do a test with the choices you see here, but i can't select anything.
PS. radio widget works
another question, how do I increase the size of the input?
widget.attrs = {'style': 'width: 275px;'}
it does not work
Currently, it's not very obvious that an item has moved.
Hey,
thanks for this library. I have a use-case that I believe is fairly normal as I've had to do the same thing in multiple different situations/projects. Using your library I've had to do some workarounds to get there.
The setup is this: I have to store annual surveys in the database. The surveys are always have a few fields that always need to be included (name, date, etc.) and other fields that change every year. So I create two models in the database:
class SurveyType(models.Model):
name = models.CharField(max_length=255)
schema = models.JSONField(default=dict)
def __str__(self):
return self.name
class SurveyEntry(models.Model):
participant_name = models.Charfield(max_length=255)
date = models.DateField()
survey_type = models.ForeignKey(
SurveyType,
on_delete=models.CASCADE,
)
survey_data = jsonformJSONField(schema=lambda instance: instance.survey_type.schema)
This looks good, but it won't work as initially when entering a new SurveyEntry
, no survey_type
has been defined. It would be good if there was a way to handle that. The work around I found was to do this to SurveyEntry
:
class SurveyEntry(models.Model):
participant_name = models.Charfield(max_length=255)
date = models.DateField()
survey_type = models.ForeignKey(
SurveyType,
on_delete=models.CASCADE,
)
survey_data = jsonformJSONField(
schema=lambda instance=None: instance.survey_type.schema
if instance and hasattr(instance, "survey_type")
else {"type": "object", "properties": {}},
null=True,
blank=True,
)
def save(self, *args, **kwargs):
if not bool(self.survey_data):
# This was likely based on the default schema. Remove again.
self.survey_data = None
return super().save(*args, **kwargs)
I installed version 2.1.0 of the lib in my project and followed the quickstart tutorial, but I am now getting an error in the page where the field is supposed to render - template "django_jsonform/editor.html" does not exist. I checked that there's no "templates" directory in the locally installed django_jsonform
package. The only folders are models and forms and the template is being referenced in JSONFormWidget
.
How do I define a field as optional? I'm trying to add an integer field, but i cannot save the form without putting in value.
schema={
'type': 'array',
'items': {
'type': 'dict',
'keys': {
'foo': {
'type': 'string',
},
'bar': {
'type': 'string',
},
},
},
},
if you edit an instance that has [] in database, even if you don't touch any of the fields, it automatically stores
[{"foo": "", "bar": ""}]
While I understand that's how django manages empty string fields, setting them to an empty string instead of null, it doesn't make sense for it to happen in cases like this. It's causing us problems because then our frontend/api tries to return this stuff and it shows an empty item.
I'm not sure how to handle this case, but here's three suggestions:
weekend_days = JSONField( blank=True, help_text="Days of the week which are considered weekend days (format is DAY_NAME:1, eg. sunday:1)", schema={ "type": "dict", "keys": { "monday": {"type": "number", "default": 1}, "tuesday": {"type": "number", "default": 0}, "wednesday": {"type": "number", "default": 0}, "thursday": {"type": "number", "default": 0}, "friday": {"type": "number", "default": 0}, "saturday": {"type": "number", "default": 1}, "sunday": {"type": "number", "default": 1}, }, }, )
In the above scenario, the weekend_days when complied sets to null, instead of 0, so when I query I get
` {
"monday": 1,
"tuesday": null,
"wednesday": null,
"thursday": null,
"friday": null,
"saturday":1,
"sunday":1,
}`
I use Django 4.1, postgres 13, django-jsonform 2.10.1
Steps to reproduce:
This happens in nested dicts. In fact, the disappeared key is added to the outer dict if outer dict also supports additional keys.
It took me a while to figure out that I had to register the model like this in the admin.py file in order for it to show up correctly:
class ModelNameForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["field_name"].widget.instance = self.instance
class Meta:
model = ModelName
exclude = []
class ModelNameAdmin(admin.ModelAdmin):
form = ModelNameForm
admin.site.register(ModelName, ModelNameAdmin)
It was hard to find that part in the documentaiton and when I found it, the documentation was incomplete.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.