art049 / art049/odmantic

Optional Embedded model and key_name not working

Open
#484 6 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.