Skip to content

SQLModel class cannot be extended with non-Pydantic basesΒ #348

@jtv8

Description

@jtv8

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 sqlmodel import SQLModel
from typing import Generic, TypeVar

T = TypeVar("T")

class ExtendedSQLModel(SQLModel, Generic[T]):
    pass

Description

SQLModel cannot be extended with bases that are not a subclass of pydantic.BaseModel, because SQLModelMetaclass.__init__ expects certain class attributes to be present on all bases. Extending SQLModel in this way may be useful if you want to make use of generics or mixins to extend its functionality.

Expected behavior:

I would expect the code snippet above to create a subclass without error, similar to this example using pydantic.BaseModel:

from pydantic import BaseModel
from typing import Generic, TypeVar

T = TypeVar("T")

class ExtendedBaseModel(BaseModel, Generic[T]):
    pass

Actual behavior:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\lib\site-packages\sqlmodel\main.py", line 327, in __init__
    config = getattr(base, "__config__")
AttributeError: type object 'Generic' has no attribute '__config__'

Operating System

Windows

Operating System Details

No response

SQLModel Version

0.0.6

Python Version

3.8.3

Additional Context

Workaround:

You can work around this issue by mixing the desired class into a subclass of pydantic.BaseModel before mixing it in to your SQLModel subclass:

from pydantic import BaseModel
from sqlmodel import SQLModel
from typing import Generic, TypeVar

T = TypeVar("T")

class ExtendedBaseModel(BaseModel, Generic[T]):
    pass

class ExtendedSQLModel(SQLModel, ExtendedBaseModel[T]):
    pass

Suggested fix:

Rewrite any lines that reference attributes from bases to handle the case where that attribute doesn't exist, e.g. change main.py:326 from:

            config = getattr(base, "__config__")

to:

            config = getattr(base, "__config__", None)

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