Django JSONField with Pydantic models as a Schema
OTHER License
Bot releases are hidden (Show)
Published by surenkov 11 months ago
Previous pre-release contained a broken package. Here's the new one (:
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.3.0a1...v0.3.0a2
Published by surenkov 11 months ago
0.3.0a1
contained a broken package. Please take a look on 0.3.0a2
if you like to test it in the wild (:This release is specifically focused on adding v2 primitives. Pydantic v1 was supported by a trickery around passed (or annotated) schema, wrapping it into intermediary RootModel to support both pydantic models and most of arbitrary annotations.
With v2, pydantic now contains the primitive -- TypeAdapter
-- which is well designed for this particular machinery.
There's one remaining primitive is to be migrated prior final 0.3.0 -- OpenAPI AutoSchema
generator, but since this library is already not super-sticky to the OpenAPI standard, I decided that alpha release could be rolled out without it.
To support both Pydantic v1 and v2, which might be useful during migration step, I added an indirection level during the import step.
0.3.0
contains implementations for both versions, with changes in v1 only required to make this compatibility layer to operate, with all behaviour remaining as in 0.2.11
.
In 0.2.*
versions, exact schema resolution had been done in three stages:
contribute_to_class
method.In this update, I decided that evaluation logic should be as simple as possible, thus keeping only stage 3, and removing all the dirty logic that supported the machinery around 1 and 2 stages.
To mitigate possible schema evaluation errors, which may appear only in runtime, the field now performs a few checks that are being performed by Django during app development lifecycle:
manage.py check
manage.py runserver
manage.py makemigrations
manage.py migrate
This check is relied on the same mechanics that you might see in plain JSONField
, complaining on passing mutable structures itself, instead of callables (Django's field.E010
warning).
Along with the schema evaluation check, the field now performes a few others, to make sure of its integrity:
pydantic.E001
(a check from the section above). The schema cannot be resolved. It is most likely a programmatic error -- forward references cannot be resolved in the Django model's execution context.pydantic.E002
. The field's default=
value cannot be serialized by the specified schema. This may lead to runtime errors during model .save()
or .objects.create(...)
methods.pydantic.E003
. If the field contains include=
or exclude=
export arguments, there could be a situation that value, written in the database, could not be restored back to python from its serialized form. This check tries to pass the specified default value (or the one that could be inferred directly from the schema, if default=
is missing), through the whole transformation cycle, yielding a warning if the value could not be transformed back to python.Additionally, JSONField
's field.E010
warning is suppressed, as it is meaningless due to the nature of field transformations -- we're always getting a new value, not reusing the one passed to default=
argument.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.11...v0.3.0a1
Published by surenkov about 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.10...v0.2.11
Published by surenkov about 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.9...v0.2.10
Published by surenkov about 1 year ago
contribute_to_class
are copied. by @TomTruck in https://github.com/surenkov/django-pydantic-field/pull/27
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.8...v0.2.9
Published by surenkov about 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.7...v0.2.8
Published by surenkov over 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.6...v0.2.7
Published by surenkov over 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.5...v0.2.6
Published by surenkov over 1 year ago
get_prep_value
and get_db_prep_value
methods for PydanticSchemaField by @surenkov in https://github.com/surenkov/django-pydantic-field/pull/20
This release fixes #19, thus Django < 4.2 users should avoid installing previous one, v0.2.4
.
I'm considering to delist 0.2.4 from PyPI to minimize the potential harm.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.4...v0.2.5
Published by surenkov over 1 year ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.3...v0.2.4
Published by surenkov over 1 year ago
setup.cfg
to the sole pyproject.toml
by @surenkov in https://github.com/surenkov/django-pydantic-field/pull/13
__init__
before calling super().__init__
by @surenkov in https://github.com/surenkov/django-pydantic-field/pull/14
Closed: https://github.com/surenkov/django-pydantic-field/issues/12
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.2...v0.2.3
Published by surenkov almost 2 years ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.1...v0.2.2
Published by surenkov about 2 years ago
The package supports Django starting from 3.1.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.2.0...v0.2.1
Published by surenkov about 2 years ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.13...v0.2.0
Published by surenkov about 2 years ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.12...v0.1.13
Published by surenkov about 2 years ago
Un additin to typed collections and pydantic types, the field now also supports typing.Union
, its special forms like typing.Optional
and (only for py 3.10+) X | Y
union annotations syntax.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.11...v0.1.12
Published by surenkov about 2 years ago
In the example below, typing linters should enforce type compatibility:
class BuildingMeta(pydantic.BaseModel):
type: Optional[BuildingTypes]
class Building(models.Model):
opt_meta: BuildingMeta = SchemaField(default={"type": "frame"}, null=True)
meta: Optional[BuildingMeta] = SchemaField(default={"type": "frame"})
Pyright will complain on both fields:
sample_app/models.py:5:32 - error: Expression of type "BuildingMeta | None" cannot be assigned to declared type "BuildingMeta"
sample_app/models.py:6:40 - error: Expression of type "ST@SchemaField" cannot be assigned to declared type "BuildingMeta | None"
Mypy has more broaden resolution for latter check, but still be able to recognise first one:
sample_app/models.py:5: error: Incompatible types in assignment (expression has type "Optional[BuildingMeta]", variable has type "BuildingMeta")
Fixing field annotations will resolve issues on both checkers:
class Building(models.Model):
opt_meta: Optional[BuildingMeta] = SchemaField(default={"type": "frame"}, null=True)
meta: BuildingMeta = SchemaField(default={"type": "frame"})
The check also enforces default=None
to have null=True
param.
default=
argumentIn addition to null enforcement, typing checks allow arbitrary values for default=
argument, as long as they are acceptable for pydantic's BaseModel.parse_obj
method. Callables are also accepted, mimicking Django's field semantics.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.10...v0.1.11
Published by surenkov about 2 years ago
Slightly improve inheritance chain, better typings for SchemaField
factory function.
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.9...v0.1.10
Published by surenkov about 2 years ago
Full Changelog: https://github.com/surenkov/django-pydantic-field/compare/v0.1.8...v0.1.9
Published by surenkov about 2 years ago
Django model fields are required to throw django.core.exceptions.ValidationError
during .to_python(value)
call.
Let's stick to that recommendation.
Convert the input value into the expected Python data type, raising
django.core.exceptions.ValidationError if the data can't be converted.