Django Structured JSON Field

This is a Django field that allows you to declare the structure of a JSON field and validate it.
Features
- Define the structure of a JSON field using Pydantic models
- Validate the JSON field against the defined structure
- Use relationships between models inside the JSON field 🤯
- Django-native
prefetch_relatedacross JSON paths —MyModel.objects.prefetch_related("structured_data__author__country")Just Works 🚀 - Easily integrate with Django Rest Framework serializers
- Admin editor for the JSON field with autocomplete search for related models 👀
Documentation
Check out our documentation for detailed guides and examples on:
- Installation and basic usage
- Working with relationships
- Prefetching relations across JSON paths
- Admin integration
- REST Framework integration
- Caching
- Settings configuration
Installation
pip install django-structured-json-field
Usage
from django.db import models
from structured.fields import StructuredJSONField
from structured.pydantic.models import BaseModel
# Define this schema as you would do with a Pydantic model
class MySchema(BaseModel):
name: str
age: int = None
def init_data():
return MySchema(name='')
# Create a model with a StructuredJSONField with the schema you defined
class MyModel(models.Model):
structured_data = StructuredJSONField(schema=MySchema, default=init_data)
Relationships
This field supports relationships between models, you can define them in your schema and they will be treated as normal django relationships. It also supports recursive schemas.
Recursion
You can define recursive schemas by declaring the attribute type as a string:
from typing import Optional, List
class MySchema(BaseModel):
name: str
age: int = None
parent: Optional['MySchema'] = None
relateds: List['MySchema'] = []
Foreign Keys
You can also define model relationships in your schema:
from structured.pydantic.fields import ForeignKey
class MySchema(BaseModel):
name: str
age: int = None
fk_field: ForeignKey['MyModel'] = None
This will treat the parent field as a normal django ForeignKey.
Tip:
You can omit the ForeignKey field and just use the model class as the type annotation:
class MySchema(BaseModel):
name: str
age: int = None
fk_field: MyModel = None
the field will still be treated as a ForeignKey if the type annotation is a subclass of django models.Model.
ManyToMany
If you need a ManyToMany relationship, you can use the QuerySet field:
from structured.pydantic.fields import QuerySet
class MySchema(BaseModel):
name: str
age: int = None
parents: QuerySet['MyModel']
QuerySet fields will generate a django object manager that will allow you to query the related objects as you would do with a normal django QuerySet.
instance = MySchema(name='test', age=10, parents=MyModel.objects.all())
# You can filter the queryset
instance.parents.filter(name='test')
# You can count the queryset
instance.parents.count()
# You can get the first element of the queryset, etc...
instance.parents.first()
Admin integration
The field is integrated with the Django admin, you can use the autocomplete search to select the related models. To allow the autocomplete search you need to include structured.urls in your urls.py file:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('structured.urls')),
]
Rest Framework integration
You can easily integrate structured fields with Django Rest Framework serializers, just use the StructuredModelSerializer as the base class for your serializer:
from rest_framework import serializers
from structured.contrib.rest_framework import StructuredModelSerializer
class MyModelSerializer(StructuredModelSerializer):
class Meta:
model = MyModel
fields = '__all__'
Errors generated by pydantic validation will be automatically translated to DRF errors.
Cache
To prevent the field from making multiple identical queries a caching technique is used. The cache is still a work in progress, please open an issue if you find any problem. Actually the cache covers all the relations inside a StructuredJSONField, optimizing the queries during the serialization process.
Cache engine progress:
- Shared cache between
ForeignKeyfields andQuerySetfields - Shared cache through nested schemas
- Shared cache through nested lists of schemas
- Shared cache between all
StructuredJSONFieldsin the same instance - Shared cache between multiple instances of the same model
- Cache invalidation mechanism
Settings
You can manage structured field behaviour modifying the STRUCTURED_FIELD setting in your settings.py file. Here a list of the available settings and their default values:
STRUCTURED_FIELD = {
'CACHE':{
'ENABLED': True,
'SHARED': False # ⚠️ EXPERIMENTAL: this enables a thread-shared cache, it's not recommended to use it in production.
},
}
Contributing
The project is open to contributions, just open an issue or a PR.
Running tests
pip install -r requirements-dev.txt
make test
Running test app
pip install -r requirements-dev.txt
python manage.py migrate
python manage.py runserver
License
This project is licensed under the MIT License - see the LICENSE file for details
Metadata
Release files for django-structured-json-field 1.7.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django_structured_json_field-1.7.2.tar.gz | 70.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_structured_json_field-1.7.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 128.1 kB
Release files / django_structured_json_field-1.7.2.tar.gz
| Download URL | django_structured_json_field-1.7.2.tar.gz |
|---|---|
| Size | 70.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7b0c7123c8313e0d9b8dc38cd6f7812ff28d2d754b64b94abc9644b805a009a7
|
|
BLAKE2b-256 checksum How to use checksums |
d50c0bd4f1279e44618685b69b1b27b880b63a611b876ee6f718e81b1a3aeb1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency logRelease files / django_structured_json_field-1.7.2-py3-none-any.whl
| Download URL | django_structured_json_field-1.7.2-py3-none-any.whl |
|---|---|
| Size | 57.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aacf660838d3e4640724c149769046d21054a686a8bfcb3cbd781eb2a4a6db7a
|
|
BLAKE2b-256 checksum How to use checksums |
09261f160b0550694e1bc69597d7e993a7418eec47497da4d656c00cb02f7feb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency logSecurity for django-structured-json-field 1.7.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_structured_json_field-1.7.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 15, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.