Overview
Django JSON Widget provides a user-friendly JSON editor with syntax highlighting for Django’s JSONField. Unfold automatically styles this widget with improved dark mode support and ensures seamless integration with your admin interface.
The widget makes editing JSON data much easier with features like syntax highlighting, automatic indentation, and validation.
Installation
Install django-json-widget
Install the package using pip: pip install django-json-widget
Add to INSTALLED_APPS
Add django-json-widget to your settings: INSTALLED_APPS = [
"unfold" ,
"django.contrib.admin" ,
# ...
"django_json_widget" ,
]
No Unfold contrib app is needed. Unfold automatically applies custom CSS to style the JSON widget with proper dark mode support.
Basic Usage
Model with JSONField
from django.db import models
class Configuration ( models . Model ):
name = models.CharField( max_length = 200 )
settings = models.JSONField( default = dict )
metadata = models.JSONField( default = dict , blank = True )
def __str__ ( self ):
return self .name
from django.contrib import admin
from django import forms
from unfold.admin import ModelAdmin
from django_json_widget.widgets import JSONEditorWidget
from .models import Configuration
class ConfigurationAdminForm ( forms . ModelForm ):
class Meta :
model = Configuration
fields = "__all__"
widgets = {
"settings" : JSONEditorWidget,
"metadata" : JSONEditorWidget,
}
@admin.register (Configuration)
class ConfigurationAdmin ( ModelAdmin ):
form = ConfigurationAdminForm
list_display = [ "name" ]
The JSON widget provides:
Syntax Highlighting : Color-coded JSON structure
Auto-Indentation : Properly formatted JSON
Validation : Real-time JSON syntax validation
Expand/Collapse : Collapse JSON sections for easier navigation
Dark Mode : Automatic theme switching with Unfold
Custom Options
Configure the widget behavior:
from django_json_widget.widgets import JSONEditorWidget
class ConfigurationAdminForm ( forms . ModelForm ):
class Meta :
model = Configuration
fields = "__all__"
widgets = {
"settings" : JSONEditorWidget(
options = {
"mode" : "code" , # 'code', 'tree', 'form', 'text', 'view'
"modes" : [ "code" , "tree" ], # Available modes
"search" : True , # Enable search
}
),
}
# Code mode (default) - Raw JSON with syntax highlighting
JSONEditorWidget( options = { "mode" : "code" })
# Tree mode - Interactive tree view
JSONEditorWidget( options = { "mode" : "tree" })
# Form mode - Form-based editing
JSONEditorWidget( options = { "mode" : "form" })
# View mode - Read-only display
JSONEditorWidget( options = { "mode" : "view" })
Multiple Modes
Allow users to switch between modes:
JSONEditorWidget(
options = {
"mode" : "code" ,
"modes" : [ "code" , "tree" , "form" , "view" ], # Available modes
}
)
Common Use Cases
API Configuration
Store API settings as JSON:
class APIConfiguration ( models . Model ):
name = models.CharField( max_length = 200 )
config = models.JSONField(
default = dict ,
help_text = "API configuration in JSON format"
)
def __str__ ( self ):
return self .name
# Example JSON data
{
"api_key" : "your-api-key" ,
"base_url" : "https://api.example.com" ,
"timeout" : 30 ,
"retry_attempts" : 3 ,
"endpoints" : {
"users" : "/api/v1/users" ,
"orders" : "/api/v1/orders"
}
}
Feature Flags
Manage feature flags:
class FeatureFlags ( models . Model ):
environment = models.CharField( max_length = 50 )
flags = models.JSONField( default = dict )
class Meta :
verbose_name_plural = "Feature flags"
# Example flags
{
"new_dashboard" : true,
"beta_features" : false,
"maintenance_mode" : false,
"rate_limits" : {
"api" : 1000 ,
"login" : 5
}
}
Product Specifications
Store flexible product attributes:
class Product ( models . Model ):
name = models.CharField( max_length = 200 )
price = models.DecimalField( max_digits = 10 , decimal_places = 2 )
specifications = models.JSONField(
default = dict ,
blank = True ,
help_text = "Product specifications"
)
# Example specifications
{
"dimensions" : {
"width" : 10 ,
"height" : 5 ,
"depth" : 3 ,
"unit" : "cm"
},
"weight" : {
"value" : 250 ,
"unit" : "g"
},
"colors" : [ "black" , "silver" , "gold" ],
"features" : [
"Waterproof" ,
"Wireless" ,
"Rechargeable"
]
}
User Preferences
Store user settings:
from django.contrib.auth import get_user_model
class UserPreferences ( models . Model ):
user = models.OneToOneField(
get_user_model(),
on_delete = models. CASCADE ,
related_name = "preferences"
)
settings = models.JSONField( default = dict )
# Example preferences
{
"theme" : "dark" ,
"language" : "en" ,
"notifications" : {
"email" : true,
"push" : false,
"sms" : false
},
"privacy" : {
"profile_visible" : true,
"show_email" : false
}
}
Working with JSON Data
Creating Records
from myapp.models import Configuration
config = Configuration.objects.create(
name = "Production API" ,
settings = {
"api_key" : "secret-key" ,
"timeout" : 30 ,
"retry" : True ,
}
)
Updating JSON Fields
config = Configuration.objects.get( id = 1 )
# Update entire field
config.settings = {
"api_key" : "new-key" ,
"timeout" : 60 ,
}
config.save()
# Update specific key
config.settings[ "timeout" ] = 45
config.save()
Querying JSON Fields
# Exact match
Configuration.objects.filter(
settings = { "timeout" : 30 }
)
# Key exists
Configuration.objects.filter(
settings__has_key = "api_key"
)
# Nested lookup
Configuration.objects.filter(
settings__timeout = 30
)
# Contains
Configuration.objects.filter(
settings__contains = { "retry" : True }
)
Advanced Admin Configuration
Multiple JSON Fields
class ConfigurationAdminForm ( forms . ModelForm ):
class Meta :
model = Configuration
fields = "__all__"
widgets = {
"settings" : JSONEditorWidget(
options = { "mode" : "tree" }
),
"metadata" : JSONEditorWidget(
options = { "mode" : "code" }
),
}
@admin.register (Configuration)
class ConfigurationAdmin ( ModelAdmin ):
form = ConfigurationAdminForm
fieldsets = [
( "Basic Information" , {
"fields" : [ "name" ],
}),
( "Settings" , {
"fields" : [ "settings" ],
}),
( "Metadata" , {
"fields" : [ "metadata" ],
"classes" : [ "collapse" ],
}),
]
Custom Validation
from django import forms
from django.core.exceptions import ValidationError
import json
class ConfigurationAdminForm ( forms . ModelForm ):
def clean_settings ( self ):
settings = self .cleaned_data[ "settings" ]
# Validate required keys
required_keys = [ "api_key" , "base_url" ]
for key in required_keys:
if key not in settings:
raise ValidationError(
f "Missing required key: { key } "
)
# Validate value types
if not isinstance (settings.get( "timeout" ), ( int , float )):
raise ValidationError(
"Timeout must be a number"
)
return settings
Read-Only JSON Display
@admin.register (Configuration)
class ConfigurationAdmin ( ModelAdmin ):
readonly_fields = [ "formatted_settings" ]
def formatted_settings ( self , obj ):
import json
from django.utils.html import format_html
formatted = json.dumps(obj.settings, indent = 2 )
return format_html(
"<pre> {} </pre>" ,
formatted
)
formatted_settings.short_description = "Settings (Read-Only)"
Styling Integration
Unfold enhances the JSON widget with:
Dark Mode Support : Automatic theme switching
Consistent Colors : Matches Unfold’s color scheme
Proper Spacing : Aligned with Unfold’s design
Border Styling : Consistent with other form fields
The widget automatically inherits Unfold’s dark mode settings, providing a seamless experience when switching themes.
Large JSON Objects
For very large JSON objects, consider:
# Use 'view' mode for read-only display
JSONEditorWidget( options = { "mode" : "view" })
# Or limit editing modes
JSONEditorWidget(
options = {
"mode" : "code" ,
"modes" : [ "code" , "view" ], # Exclude tree/form modes
}
)
Database Indexing
Add GIN indexes for JSON queries (PostgreSQL):
from django.contrib.postgres.indexes import GinIndex
class Configuration ( models . Model ):
settings = models.JSONField( default = dict )
class Meta :
indexes = [
GinIndex( fields = [ "settings" ]),
]
If you need different JSON editing experiences:
# Use Unfold's WYSIWYG for rich text in JSON
from unfold.widgets import WysiwygWidget
# Or custom textarea
from django.forms import Textarea
widgets = {
"settings" : Textarea( attrs = { "rows" : 10 }),
}
Resources
Django JSON Widget Official package documentation
JSONField Documentation Django’s JSONField reference
Always validate JSON data on the backend. Client-side validation in the widget is helpful but not sufficient for security.