Optional Embedded model and key_name not working
- Dominant language
- Python
- Stars
- 1.2k
- Forks
- 97
- PR merge metrics
- No merged PRs in 30d
Description
# Bug
I have the following model:
```python
class CompanyRelation(EmbeddedModel):
company_id: str = Field(key_name="companyId")
class Person(Model):
model_config: ClassVar = {
"collection": "Main",
"parse_doc_with_default_factories": True,
}
company_relations: Optional[list[CompanyRelation]] = Field(
key_name="companyRelation", default_factory=list
)
```
It was working before I made the `company_relations` field `Optional` (which I had to because sometimes the key is missing in MongoDB records)
When I try to fetch valid records I now get errors like:
```
Traceback (most recent call last):
File "/opt/python/odmantic/model.py", line 802, in model_validate_doc
instance = cls.model_validate(obj)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/python/pydantic/main.py", line 509, in model_validate
return cls.__pydantic_validator__.validate_python(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 41 validation errors for Person
company_relations.0.company_id
Field required [type=missing, input_value={'companyId': '5d19ea5ed4...'roles': ['OrderAdmin']}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.6/v/missing
company_relations.1.company_id
Field required [type=missing, input_value={'companyId': '64df2da547...'roles': ['OrderAdmin']}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.6/v/missing
company_relations.2.company_id
Field required [type=missing, input_value={'companyId': '64df2da647...'roles': ['OrderAdmin']}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.6/v/missing
company_relations.3.company_id
Field required [type=missing, input_value={'companyId': '64df2da747...'roles': ['OrderAdmin']}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.6/v/missing
company_relations.4.company_id
Field required [type=missing, input_value={'companyId': '64df2da847...'roles': ['OrderAdmin']}, input_type=dict]
For further information visit
...
```
Notably the `companyId` field exists in the input.
If I remove the `Optional` it works (but can't cope with missing field).
If I replace `company_id: str = Field(key_name="companyId")` with `companyId: str # noqa: N815` and keep the `Optional` it works.
So it seems to be the combination of `Optional` + `key_name` that has the problem.
### Current Behavior
See above.
Also I can instantiate the `CompanyRelation` directly from the sub data (again bypassing whatever the `Optional` on parent model has done to break things)
### Expected behavior
No error.
### Environment
- ODMantic version: 1.0.2
- MongoDB version: I don't think it matters
- Pydantic infos (output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())`):
```
pydantic version: 2.6.4
pydantic-core version: 2.16.3
pydantic-core build: profile=release pgo=true
python version: 3.11.5 (main, Sep 18 2023, 15:04:25) [Clang 14.0.3 (clang-1403.0.22.14.1)]
platform: macOS-14.4.1-arm64-arm-64bit
related packages: typing_extensions-4.11.0 pydantic-settings-2.2.1
```
- Version of additional modules (if relevant):
- ...
**Additional context**
_Add any other context about the problem here._
Contributor guide
Research direction
Start in odmantic/model.py at model_validate_doc, then reproduce the shown Person and CompanyRelation definitions with an Optional list and Field(key_name="companyId"). Compare validation with and without Optional and with the direct field name; done means the stored companyId values validate correctly while missing parent fields remain supported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- mongodb, python
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100