Skip to content

Commit

Permalink
Bypass field validation on model instantiation if it does not contain…
Browse files Browse the repository at this point in the history
… a default= argument
  • Loading branch information
surenkov committed May 5, 2024
1 parent b6bb473 commit bb9b39a
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 7 deletions.
17 changes: 14 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
DJANGO_SETTINGS_MODULE ?= "tests.settings.django_test_settings"

.PHONY: install build test lint upload upload-test clean
export DJANGO_SETTINGS_MODULE=tests.settings.django_test_settings

.PHONY: install
install:
python3 -m pip install build twine
python3 -m pip install -e .[dev,test]

.PHONY: build
build:
python3 -m build

.PHONY: migrations
migrations:
python3 -m django makemigrations --noinput

.PHONY: runserver
runserver:
python3 -m django migrate && \
python3 -m django runserver

.PHONY: check
check:
python3 -m django check

.PHONY: test
test: A=
test:
pytest $(A)

.PHONY: lint
lint: A=.
lint:
python3 -m mypy $(A)

.PHONY: upload
upload:
python3 -m twine upload dist/*

.PHONY: upload-test
upload-test:
python3 -m twine upload --repository testpypi dist/*

.PHONY: clean
clean:
rm -rf dist/*
4 changes: 3 additions & 1 deletion django_pydantic_field/v1/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def contribute_to_class(self, cls, name, *args, **kwargs):
field: "PydanticSchemaField"

def __set__(self, obj, value):
obj.__dict__[self.field.attname] = self.field.to_python(value)
if self.field.has_default() or value is not None:
value = self.field.to_python(value)
obj.__dict__[self.field.attname] = value


class PydanticSchemaField(JSONField, t.Generic[base.ST]):
Expand Down
9 changes: 6 additions & 3 deletions django_pydantic_field/v2/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ def __set_name__(self, owner, name):
self.field.adapter.bind(owner, name)

def __set__(self, obj, value):
obj.__dict__[self.field.attname] = self.field.to_python(value)
if self.field.has_default() or value is not None:
value = self.field.to_python(value)
obj.__dict__[self.field.attname] = value


class PydanticSchemaField(JSONField, ty.Generic[types.ST]):
descriptor_class: type[DeferredAttribute] = SchemaAttribute
descriptor_class: ty.ClassVar[type[DeferredAttribute]] = SchemaAttribute
adapter: types.SchemaAdapter

def __init__(
Expand Down Expand Up @@ -118,7 +120,8 @@ def check(self, **kwargs: ty.Any) -> list[checks.CheckMessage]:

try:
# Test that the default value conforms to the schema.
self.get_prep_value(self.get_default())
if self.has_default():
self.get_prep_value(self.get_default())
except pydantic.ValidationError as exc:
message = f"Default value cannot be adapted to the schema. Pydantic error: \n{str(exc)}"
performed_checks.append(checks.Error(message, obj=self, id="pydantic.E002"))
Expand Down

0 comments on commit bb9b39a

Please sign in to comment.