{"id":15441979,"url":"https://github.com/surenkov/django-pydantic-field","last_synced_at":"2026-01-17T17:38:03.269Z","repository":{"id":45684559,"uuid":"513956026","full_name":"surenkov/django-pydantic-field","owner":"surenkov","description":"Type-Safe Pydantic Schemas for Django JSONFields","archived":false,"fork":false,"pushed_at":"2026-01-14T18:39:10.000Z","size":461,"stargazers_count":201,"open_issues_count":18,"forks_count":17,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-16T21:37:45.750Z","etag":null,"topics":["django","jsonfield","pydantic","schema"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/django-pydantic-field/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/surenkov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-14T15:35:53.000Z","updated_at":"2026-01-14T18:39:14.000Z","dependencies_parsed_at":"2026-01-06T15:07:46.106Z","dependency_job_id":null,"html_url":"https://github.com/surenkov/django-pydantic-field","commit_stats":{"total_commits":178,"total_committers":8,"mean_commits":22.25,"dds":0.050561797752809,"last_synced_commit":"4c6556675282f2dbccf11e0c5b7f6d86fc9e1f0c"},"previous_names":[],"tags_count":57,"template":false,"template_full_name":null,"purl":"pkg:github/surenkov/django-pydantic-field","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surenkov%2Fdjango-pydantic-field","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surenkov%2Fdjango-pydantic-field/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surenkov%2Fdjango-pydantic-field/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surenkov%2Fdjango-pydantic-field/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/surenkov","download_url":"https://codeload.github.com/surenkov/django-pydantic-field/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surenkov%2Fdjango-pydantic-field/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28513757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","jsonfield","pydantic","schema"],"created_at":"2024-10-01T19:24:43.926Z","updated_at":"2026-01-17T17:38:03.244Z","avatar_url":"https://github.com/surenkov.png","language":"Python","funding_links":[],"categories":["Object Mapping"],"sub_categories":[],"readme":"[![PyPI Version](https://img.shields.io/pypi/v/django-pydantic-field)](https://pypi.org/project/django-pydantic-field/)\n[![Lint and Test Package](https://github.com/surenkov/django-pydantic-field/actions/workflows/python-test.yml/badge.svg)](https://github.com/surenkov/django-pydantic-field/actions/workflows/python-test.yml)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/django-pydantic-field)](https://pypistats.org/packages/django-pydantic-field)\n[![Supported Python Versions](https://img.shields.io/pypi/pyversions/django-pydantic-field)](https://pypi.org/project/django-pydantic-field/)\n[![Supported Django Versions](https://img.shields.io/pypi/frameworkversions/django/django-pydantic-field)](https://pypi.org/project/django-pydantic-field/)\n\n# Type-Safe Pydantic Schemas for Django JSONFields\n\n`django-pydantic-field` provides a way to use Pydantic models as schemas for Django's `JSONField`.\nIt offers full support for Pydantic v1 and v2, type safety and integration with Django's ecosystem, including Forms and Django REST Framework.\n\n## Highlights\n\n- **Unified API**: Transparent support for Pydantic v1 and v2 through the `SchemaAdapter`s.\n- **Type-Safe**: Support for static type checking (ty/mypy/pyright) with type inference for models and annotations.\n- **Forward References**: Lazy resolution of forward references, allowing schemas to be defined anywhere.\n- **Django Integration**: Support for Django Forms and the Admin interface.\n- **DRF Support**: Typed Serializers, Parsers, and Renderers with automatic OpenAPI schema generation via DRF's native schema generator.\n\n## Installation\n\n```bash\npip install django-pydantic-field\n```\n\n## Basic Usage\n\nThe `SchemaField` can be used by passing the schema as the first argument (Django-like style) or by using type annotations.\n\n```python\nimport pydantic\nimport typing\n\nfrom django.db import models\nfrom django_pydantic_field import SchemaField\n\n\nclass Foo(pydantic.BaseModel):\n    count: int\n    slug: str = \"default\"\n\n\nclass MyModel(models.Model):\n    # Django-like style (explicit schema)\n    bar = SchemaField(Foo, default={\"count\": 5})\n\n    # Annotation-based style (Pydantic-like)\n    foo: Foo = SchemaField()\n\n    # Supports standard Python types and annotations\n    items: list[Foo] = SchemaField(default=list)\n\n    # null=True correctly infers t.Optional[Foo] for type checkers\n    optional_foo = SchemaField(Foo, null=True, default=None)\n\nmodel = MyModel(foo={\"count\": 42})\nmodel.save()\n\n# Data is automatically parsed into Pydantic models\nassert isinstance(model.foo, Foo)\nassert model.foo.count == 42\n\ntyping.assert_type(model.optional_foo, Foo | None)\n```\n\n### Supported Types\n\nAny type supported by Pydantic can be used as a schema:\n- `pydantic.BaseModel` and `pydantic.RootModel` (v2)\n- Standard Python types (`list[str]`, `dict[int, float]`, etc.)\n- `dataclasses.dataclass` and `TypedDict` protocols\n- `typing.Annotated` with metadata.\n\n```python\nfrom typing import Annotated\nfrom pydantic import Field\n\n\nclass AdvancedModel(models.Model):\n    # Annotated with validation rules\n    positive_ints: Annotated[list[int], Field(min_length=1)] = SchemaField()\n```\n\n### Forward References \u0026 Lazy Resolution\n\n`SchemaField` supports forward references via string literals or `typing.ForwardRef`. Resolution is deferred until the first time the field is accessed.\n\n```python\nimport typing\n\n\nclass MyModel(models.Model):\n    foo = SchemaField(typing.ForwardRef(\"DeferredFoo\"))\n    another_foo: \"DeferredFoo\" = SchemaField()\n\n\nclass DeferredFoo(pydantic.BaseModel):\n    ...\n```\n\n## Pydantic Version Support\n\nThe package automatically detects the Pydantic version in your environment and adapts accordingly.\n\nFor Pydantic v2 environments, you can still explicitly use Pydantic v1 models by importing from the `.v1` subpackage:\n\n```python\nfrom pydantic import v1 as pydantic_v1\nfrom django_pydantic_field.v1 import SchemaField as SchemaFieldV1\n\n\nclass LegacySchema(pydantic_v1.BaseModel):\n    ...\n\n\nclass LegacyModel(models.Model):\n    legacy_field = SchemaFieldV1(LegacySchema)\n```\n\n## Django Forms \u0026 Admin\n\nIt is possible to create Django forms, which would validate against the given schema:\n\n```python\nfrom django import forms\nfrom django_pydantic_field.forms import SchemaField\n\n\nclass FooForm(forms.Form):\n    field = SchemaField(Foo)\n\n\nform = FooForm(data={\"field\": '{\"slug\": \"asdf\", \"count\": 1}'})\nassert form.is_valid()\n```\n\n### `django-jsonform` support\n\nFor a better user experience in the Admin, you can use [`django-jsonform`](https://django-jsonform.readthedocs.io), which provides a dynamic editor based on the Pydantic model's JSON schema.\n\n```python\nfrom django.contrib import admin\nfrom django_pydantic_field import fields\nfrom django_jsonform.widgets import JSONFormWidget\n\nclass MyModelAdmin(admin.ModelAdmin):\n    formfield_overrides = {\n        fields.PydanticSchemaField: {\"widget\": JSONFormWidget},\n    }\n```\n\n## Django REST Framework\n\n### Serializers\n\n```python\nfrom rest_framework import serializers\nfrom django_pydantic_field.rest_framework import SchemaField\n\n\nclass MySerializer(serializers.Serializer):\n    pydantic_field = SchemaField(Foo)\n```\n\n### Typed Views (Parsers \u0026 Renderers)\n\nYou can use `SchemaParser` and `SchemaRenderer` to handle Pydantic models directly in your views.\n\n```python\nfrom rest_framework.decorators import api_view, parser_classes, renderer_classes\nfrom rest_framework.response import Response\nfrom django_pydantic_field.rest_framework import SchemaParser, SchemaRenderer\n\n@api_view([\"POST\"])\n@parser_classes([SchemaParser[Foo]])\n@renderer_classes([SchemaRenderer[list[Foo]]])\ndef foo_view(request):\n    # request.data is a Foo instance\n    instance: Foo = request.data\n    return Response([instance])\n```\n\n### OpenAPI Generation\n\n`django-pydantic-field` provides an `AutoSchema` that automatically generates OpenAPI definitions for your Pydantic-backed DRF components.\n```python\nfrom django_pydantic_field.rest_framework import AutoSchema\n\nclass SampleView(generics.RetrieveAPIView):\n    serializer_class = MySerializer\n    schema = AutoSchema()\n```\n\n## System Checks\n\nThe field performs validation during Django's `manage.py check` command:\n- `pydantic.E001`: Schema resolution errors.\n- `pydantic.E002`: Default value serialization errors.\n- `pydantic.W003`: Data integrity warnings for `include`/`exclude` configurations.\n\n## Contributing\nTo get `django-pydantic-field` up and running in development mode:\n1.  [Install `uv`](https://docs.astral.sh/uv/getting-started/installation/);\n2.  Install the project and its dependencies: `uv sync`;\n3.  Setup `pre-commit`: `pre-commit install`.\n4.  Run tests: `make test`.\n5.  Run linters: `make lint`.\n\n## Acknowledgement\n* [Churkin Oleg](https://gist.github.com/Bahus/98a9848b1f8e2dcd986bf9f05dbf9c65) for his Gist as a source of inspiration\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurenkov%2Fdjango-pydantic-field","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsurenkov%2Fdjango-pydantic-field","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurenkov%2Fdjango-pydantic-field/lists"}