1

I generated a Pydantic model and would like to import it into SQLModel. Since said model does not inherit from the SQLModel class, it is not registered in the metadata which is why

SQLModel.metadata.create_all(engine)

just ignores it.

In this discussion I found a way to manually add models:

SQLModel.metadata.tables["hero"].create(engine)

But doing so throws a KeyError for me.

SQLModel.metadata.tables["sopro"].create(engine)
KeyError: 'sopro'

My motivation for tackling the problem this way is that I want to generate an SQLModel from a simple dictionary like this:

model_dict = {"feature_a": int, "feature_b": str}

And in this SO answer, I found a working approach. Thank you very much in advance for your help!

Daniil Fajnberg
  • 12,753
  • 2
  • 10
  • 41
inviridi
  • 13
  • 2

1 Answers1

1

As far as I know, it is not possible to simply convert an existing Pydantic model to an SQLModel at runtime. (At least as of now.)

There are a lot of things that happen during model definition. There is a custom meta class involved, so there is no way that you can simply substitute a regular Pydantic model class for a real SQLModel class, short of manually monkeypatching all the missing pieces.

That being said, you clarified that your actual motivation was to be able to dynamically create an SQLModel class at runtime from a dictionary of field definitions. Luckily, this is in fact possible. All you need to do is utilize the Pydantic create_model function and pass the correct __base__ and __cls_kwargs__ arguments:

from pydantic import create_model
from sqlmodel import SQLModel

field_definitions = {
    # your field definitions here
}

Hero = create_model(
    "Hero",
    __base__=SQLModel,
    __cls_kwargs__={"table": True},
    **field_definitions,
)

With that, SQLModel.metadata.create_all(engine) should create the corresponding database table according to your field definitions.

See this question for more details.

Be sure to use correct form for the field definitions, as the example you gave would not be valid. As the documentation says, you need to define fields in the form of 2-tuples (or just a default value):

model_dict = {
    "feature_a": (int, ...),
    "feature_b": (str, ...),
    "feature_c": 3.14,
}

Hope this helps.

Daniil Fajnberg
  • 12,753
  • 2
  • 10
  • 41
  • Thanks a lot for this interesting avenue and the detailed answer! The model got properly generated from the start but sqlalchemy complained about a missing primary key column. was in the link you shared. All perfect now. Thank you so much! – inviridi Oct 25 '22 at 08:35