Skip to content

Commit

Permalink
Introduce method to_django turning obj into django model obj
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathan-s committed May 26, 2024
1 parent c1e68e3 commit 64b818e
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,4 @@ dmypy.json

# Not necessary for libs, see https://github.com/python-poetry/poetry/issues/7488
poetry.lock
notes.md
25 changes: 24 additions & 1 deletion djantic/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def __new__(mcs, name: str, bases: tuple, namespace: dict, **kwargs):
getattr(model_field[1], "alias", None) or field_name: field_name
for field_name, model_field in field_values.items()
}

model_schema = create_model(
name,
__base__=cls,
Expand Down Expand Up @@ -251,7 +252,29 @@ def from_orm(cls, *args, **kwargs):
return cls.from_django(*args, **kwargs)

@classmethod
def from_django(cls, objs, many=False, context={}, dump=False):
def to_django(cls, objs, many=False, validate=True):
Model = cls.model_config["model"]
if many:
# TODO, support for generators, possibly return generator.
is_not_dict = False if isinstance(objs[0], dict) else True
django_objs = []
for data in objs:
obj = Model(**data.dict()) if is_not_dict else Model(**data)
if validate:
obj.clean_fields()
django_objs.append(obj)
return django_objs

if not isinstance(objs, dict):
objs = objs.dict()

obj = Model(**objs)
if validate:
obj.clean_fields()
return obj

@classmethod
def from_django(cls, objs, many=False, context={}):
# TODO is context really passed into model_validate, test this
cls.context = context
if many:
Expand Down
97 changes: 97 additions & 0 deletions tests/test_to_django.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import pytest
from testapp.models import User
from django.core.exceptions import ValidationError

from pydantic import ConfigDict
from djantic import ModelSchema


@pytest.fixture
def user():
user = User.objects.create(
first_name="Jordan", last_name="Eremieff", email="[email protected]"
)
return user


@pytest.mark.django_db
def test_to_django_validation_failure(user):
"""
An incomplete schema throws a ValidationError
"""

class UserSchema(ModelSchema):
model_config = ConfigDict(model=User, include=["id", "first_name"])

schema = UserSchema.from_django(user)

with pytest.raises(ValidationError):
UserSchema.to_django(schema.model_dump())

with pytest.raises(ValidationError):
UserSchema.to_django(schema)


@pytest.mark.django_db
def test_validate_false(user):
"""
Optionally you can choose to not validate in to django,
you may then need to add more fields for the object to be valid
"""

class UserSchema(ModelSchema):
model_config = ConfigDict(model=User, include=["id", "first_name"])

schema = UserSchema.from_django(user)

obj = UserSchema.to_django(schema, validate=False)

assert obj.email != user.email, "No email in schema, so is not added in object"
assert obj.id == user.id
assert obj.first_name == user.first_name


@pytest.mark.django_db
def test_many_objects(user):
"""Test many objects"""
class UserSchema(ModelSchema):
model_config = ConfigDict(model=User)

schema = UserSchema.from_django(user)
obj_schema = UserSchema.to_django([schema, schema], many=True)

assert len(obj_schema) == 2
assert obj_schema[0].id == user.id
assert obj_schema[1].id == user.id


@pytest.mark.django_db
def test_invalid_many_objs(user):
"""Validation works as expected using many objs"""
class UserSchema(ModelSchema):
model_config = ConfigDict(model=User, include=["id"])

schema = UserSchema.from_django(user)
with pytest.raises(ValidationError):
UserSchema.to_django([schema], many=True)


@pytest.mark.django_db
def test_with_foreign_key_models():
pass


@pytest.mark.django_db
def test_successful_transform(user):
"""A successful transform from dict/schema to django obj"""

class UserSchema(ModelSchema):
model_config = ConfigDict(model=User)

schema = UserSchema.from_django(user)

obj_dump = UserSchema.to_django(schema.model_dump())
obj_schema = UserSchema.to_django(schema)

assert user == obj_dump
assert user == obj_schema

0 comments on commit 64b818e

Please sign in to comment.