py-automapper
py-automapper copied to clipboard
Custom mapping estrange behavior when creating object in SQL Alchemy
I'm trying to add a field mapping, but when it has more than one level it is not getting the value. The value I want to map is inside "TodoDomain.user.id". I want this to work with preregistered mapping (which I cannot make it work)
from dataclasses import dataclass
from typing import Optional
from uuid import uuid4
from automapper import mapper
@dataclass
class UserDomain:
id: int
name: str
email: str
@dataclass
class UserModel:
id: int
name: str
email: str
@dataclass
class TodoDomain:
description: str
user: UserDomain
@dataclass
class TodoModel:
description: str
user: UserDomain
user_id: Optional[int] = None
user = UserDomain(id=1, name="carlo", email="mail_carlo")
todo = TodoDomain(description="todo_carlo", user=user)
mapper.add(UserDomain, UserModel)
# This doesn't work. user_id is None
# mapper.add(TodoDomain, TodoModel)
# This works properly. user_id is 1
todo = mapper.to(TodoModel).map(todo, fields_mapping={"user_id": todo.user.id})
print(todo.__dict__)
I am also interested on this. @anikolaienko can you help on this issue?
This is by design.
Implicit mapping of fields between different levels
can be very confusing and produce unpredictable behaviour.
Use explicit mapping as described in your example.
E.g.
from dataclasses import dataclass
@dataclass
class UserDomain:
id: int
name: str
email: str
@dataclass
class TodoDomain:
description: str
user: UserDomain
@dataclass
class TodoModel:
description: str
user: UserDomain
user_id: Optional[int] = None
user = UserDomain(id=1, name="carlo", email="mail_carlo")
todo = TodoDomain(description="todo_carlo", user=user)
mapper.add(TodoDomain, TodoModel)
todo_model = mapper.map(todo)
# Implicit field mapping between parent and child objects is not supported
# TodoDomain.user.user_id should not map to TodoModel.user_id implicitly
assert todo_model.user_id is None # True
# Workaround: use explicit mapping
todo_model = mapper.map(todo, fields_mapping={"user_id": todo.user.id})
assert todo_model.user_id == 1 # True
Added a test case: https://github.com/anikolaienko/py-automapper/blob/feature/upgrade-dependencies-and-fix-ci/tests/test_issue_18_implicit_child_field_mapping.py