Skip to content

Class .... is not mapped with polymorphic identity #438

@zopyx

Description

@zopyx

First Check

  • I added a very descriptive title to this issue.
  • I used the GitHub search to find a similar issue and didn't find it.
  • I searched the SQLModel documentation, with the integrated search.
  • I already searched in Google "How to X in SQLModel" and didn't find any information.
  • I already read and followed all the tutorial in the docs and didn't find an answer.
  • I already checked if it is not related to SQLModel but to Pydantic.
  • I already checked if it is not related to SQLModel but to SQLAlchemy.

Commit to Help

  • I commit to help with one of those options 👆

Example Code

from typing import Optional
import uuid
from typing import List

from sqlmodel import Field, SQLModel, create_engine, Session, Relationship
from uuid import UUID


class InvoiceRequest(SQLModel, table=True):

    __tablename__ = "invoice_requests"

    id: UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    product: str | None = None
    request_type: str | None = None

    invoices : List["Invoice"] = Relationship(back_populates="invoice_request")

    def add_invoices(self):
        self.invoices.append(InvoiceReversal())
        self.invoices.append(Invoice())


class Invoice(SQLModel, table=True):

    __tablename__ = "invoices"

    id: UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    invoice_type: str = Field(default="regular")

    invoice_request_id: UUID | None = Field(default=None, foreign_key="invoice_requests.id")
    invoice_request: InvoiceRequest = Relationship(back_populates="invoices")

    __mapper_args__ = {
        "polymorphic_on": 'invoice_type',
        "polymorphic_identity": "regular",
    }

class InvoiceReversal(Invoice, table=True):

    __mapper_args__ = {
        "polymorphic_identity": "reversal",
    }

class InvoiceCorrection(Invoice, table=True):


    __mapper_args__ = {
        "polymorphic_identity": "correction",
    }


db_fn = "db.sqlite"
db_url = f"sqlite:///{db_fn}"
engine = create_engine(db_url, echo=True)
SQLModel.metadata.create_all(engine)



with Session(engine) as session:
    ivr = InvoiceRequest(product="2", request_type="abc")
    ivr.add_invoices()
    session.add(ivr)
    session.commit()

Description

I have this PoC-style code that would model a 1:n relationship between one InvoiceRequest and multiple Invoices.

There are several invoice types ÌnvoiceReversal and InvoiceCorrection that are modelled using the inheritance from Invoice class and polymorphic identity.

However. the derived classes are obviously not mapped:

sqlalchemy.orm.exc.UnmappedClassError: Class '__main__.InvoiceReversal' is not mapped

I could not find a solution how to resolve this.

Operating System

Linux

Operating System Details

Linux

SQLModel Version

SQLAlchemy==1.4.40

Python Version

3.10

Additional Context

python3 foo2.py
2022-09-06 11:55:17,985 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-09-06 11:55:17,985 INFO sqlalchemy.engine.Engine PRAGMA main.table_info("invoice_requests")
2022-09-06 11:55:17,985 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-09-06 11:55:17,985 INFO sqlalchemy.engine.Engine PRAGMA main.table_info("invoices")
2022-09-06 11:55:17,985 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-09-06 11:55:17,986 INFO sqlalchemy.engine.Engine COMMIT
Traceback (most recent call last):
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/sonnen/maia/planner/foo2.py", line 63, in <module>
    session.add(ivr)
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2626, in add
    self._save_or_update_state(state)
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2642, in _save_or_update_state
    for o, m, st_, dct_ in mapper.cascade_iterator(
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/orm/mapper.py", line 3230, in cascade_iterator
    queue = deque(
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/orm/relationships.py", line 2020, in cascade_iterator
    instance_mapper = instance_state.manager.mapper
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 1113, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/home/ajung/src/sonnen/sonnen-maia-proof-of-concept/.venv/lib/python3.10/site-packages/sqlalchemy/orm/instrumentation.py", line 204, in mapper
    raise exc.UnmappedClassError(self.class_)

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions