odmantic icon indicating copy to clipboard operation
odmantic copied to clipboard

Unexpected `id` field when inheriting a Model with custom `primary_field`

Open noamsto opened this issue 1 year ago • 1 comments

Bug

When inheriting a model a Model with a custom primary field, automatic meaningless id field is being populated. see: image

Current Behavior

Automatic id field is created.

Expected behavior

Automatic id field shouldn't be created, just like the Super class.

Environment

  • ODMantic version: 1.0.2
  • MongoDB version: 7.0.12
  • Pydantic infos (output of python -c "import pydantic.utils; print(pydantic.utils.version_info())):
             pydantic version: 2.9.1
        pydantic-core version: 2.23.3
          pydantic-core build: profile=release pgo=false
                 install path: /home/noams/Data/git/factify-dal/.venv/lib/python3.12/site-packages/pydantic
               python version: 3.12.4 (main, Jun  6 2024, 18:26:44) [GCC 13.3.0]
                     platform: Linux-6.10.9-x86_64-with-glibc2.39
             related packages: pydantic-settings-2.5.2 typing_extensions-4.12.2 fastapi-0.112.4 mypy-1.11.2
                       commit: unknown

...
  • Version of additional modules (if relevant):
    • ...

Additional context

Add any other context about the problem here.

noamsto avatar Sep 16 '24 09:09 noamsto

I assume here is the problem: https://github.com/art049/odmantic/blob/master/odmantic/model.py#L216

odm_fields: Dict[str, ODMBaseField] = {}

My guess is that every time an inheritance is made, this line always resets the fields:

In [1]: Document.__odm_fields__
Out[1]: {'document_id': <odmantic.field.ODMField at 0x74784a41d9f0>}

In [2]: ResponseDocument.__odm_fields__
Out[2]: {'id': <odmantic.field.ODMField at 0x74784c703c70>}

In [3]: ResponseDocument.document_id
AttributeError: document_id

# Strange behavior!
In [4]: ResponseDocument().document_id
Out [4]: UUID('ac83a164-19fe-42c2-b1c5-9a702a9093ca')

If I'm right about this, it will be a laborious problem to solve.

If it were a simple inheritance it wouldn't be difficult to do:

odm_fields: Dict[str, ODMBaseField] = self.__odm_fields__ if hasattr(self, '__odm_fields__') else {}

But it seems that the library is using metaclass, which means that this occurs before the class is built, and, in other words __odm_fields__ will never exist, to be able to obtain the existing fields it is necessary that the class is already ready.

d3cryptofc avatar Oct 30 '24 20:10 d3cryptofc