fastapi - Converting SQLAlchemy model to custom Pydantic model - Stack Overflow

I would like to convert a SQLAlchemy model to a custom Pydantic model.For instance, here is my SQLAlch

I would like to convert a SQLAlchemy model to a custom Pydantic model.

For instance, here is my SQLAlchemy one of my models:

class Program(Base):
    __tablename__ = "programs"

    id: Mapped[int] = mapped_column(primary_key=True)
    name_id: Mapped[int] = mapped_column(ForeignKey("localizations.id"))
    name: Mapped["Localization"] = relationship(foreign_keys="Program.name_id")

class Language(Base):
    __tablename__ = "languages"

    id: Mapped[str] = mapped_column(primary_key=True)
    name: Mapped[int] = mapped_column()


class Localization(Base):
    __tablename__ = "localizations"

    id: Mapped[int] = mapped_column(primary_key=True)
    translations: Mapped[List["Translation"]] = relationship(back_populates="localization")


class Translation(Base):
    __tablename__ = "translations"

    id: Mapped[int] = mapped_column(primary_key=True)
    localization_id: Mapped[int] = mapped_column(ForeignKey("localizations.id"))
    localization: Mapped["Localization"] = relationship(back_populates="translations")
    text: Mapped[str] = mapped_column()
    language_id: Mapped[str] = mapped_column(ForeignKey("languages.id"))

I would like to create a response in the following format for a program:

{
    id: 1,
    name: "My localized name"
}

I found a way to do it using dictionaries, but I would like to know if it is possible to create a Pydantic model indicating that my name field would be a Translation of a Localization of the Program.name.

I hope I am clear!

Thanks for reading! :)

I would like to convert a SQLAlchemy model to a custom Pydantic model.

For instance, here is my SQLAlchemy one of my models:

class Program(Base):
    __tablename__ = "programs"

    id: Mapped[int] = mapped_column(primary_key=True)
    name_id: Mapped[int] = mapped_column(ForeignKey("localizations.id"))
    name: Mapped["Localization"] = relationship(foreign_keys="Program.name_id")

class Language(Base):
    __tablename__ = "languages"

    id: Mapped[str] = mapped_column(primary_key=True)
    name: Mapped[int] = mapped_column()


class Localization(Base):
    __tablename__ = "localizations"

    id: Mapped[int] = mapped_column(primary_key=True)
    translations: Mapped[List["Translation"]] = relationship(back_populates="localization")


class Translation(Base):
    __tablename__ = "translations"

    id: Mapped[int] = mapped_column(primary_key=True)
    localization_id: Mapped[int] = mapped_column(ForeignKey("localizations.id"))
    localization: Mapped["Localization"] = relationship(back_populates="translations")
    text: Mapped[str] = mapped_column()
    language_id: Mapped[str] = mapped_column(ForeignKey("languages.id"))

I would like to create a response in the following format for a program:

{
    id: 1,
    name: "My localized name"
}

I found a way to do it using dictionaries, but I would like to know if it is possible to create a Pydantic model indicating that my name field would be a Translation of a Localization of the Program.name.

I hope I am clear!

Thanks for reading! :)

Share Improve this question asked Nov 18, 2024 at 16:24 TheJofTheJof 1258 bronze badges 6
  • I don't get what you want. You can create every pydantic model you want, you just have to fill it with senseful data. Which part from "Got my DB response" to "Create API response" do you have problems with? – lord_haffi Commented Nov 20, 2024 at 13:51
  • @lord_haffi I would like to be able to automatically map a model instance into a specific form. – TheJof Commented Nov 21, 2024 at 9:16
  • What kind of automation? Why can't you just write a function which takes the ORMs, extracts the information you want and creates a respective response model? – lord_haffi Commented Nov 21, 2024 at 21:26
  • Of course, you could also create a view for this but I don't know if SQLAlchemy supports ORM for database views. – lord_haffi Commented Nov 21, 2024 at 21:29
  • I did write a function for that, but as I have many base classes using a localization, I would like to be able to write it more efficiently. – TheJof Commented Nov 24, 2024 at 18:58
 |  Show 1 more comment

1 Answer 1

Reset to default 0

As I wrote in the comments, I'd suggest using database views. I found an example of how you can tweak SQLAlchemy to do this here: https://github/sqlalchemy/sqlalchemy/wiki/Views

I didn't test the code and I don't really understand your model, so you have to write the join query yourself. But try something along these lines:

import sqlalchemy as sa
from sqlalchemy.ext import compiler
from sqlalchemy.schema import DDLElement
from sqlalchemy.sql import table


class CreateView(DDLElement):
    def __init__(self, name, selectable):
        self.name = name
        self.selectable = selectable


class DropView(DDLElement):
    def __init__(self, name):
        self.name = name


@compilerpiles(CreateView)
def _create_view(element, compiler, **kw):
    return "CREATE VIEW %s AS %s" % (
        element.name,
        compiler.sql_compiler.process(element.selectable, literal_binds=True),
    )


@compilerpiles(DropView)
def _drop_view(element, compiler, **kw):
    return "DROP VIEW %s" % (element.name)


def view_exists(ddl, target, connection, **kw):
    return ddl.name in sa.inspect(connection).get_view_names()


def view_doesnt_exist(ddl, target, connection, **kw):
    return not view_exists(ddl, target, connection, **kw)


def view(name, metadata, selectable):
    t = table(name)

    t._columns._populate_separate_keys(
        col._make_proxy(t) for col in selectable.selected_columns
    )

    sa.event.listen(
        metadata,
        "after_create",
        CreateView(name, selectable).execute_if(callable_=view_doesnt_exist),
    )
    sa.event.listen(
        metadata, "before_drop", DropView(name).execute_if(callable_=view_exists)
    )
    return t


class LocalizedName(Base):
    __table__ = view(
            "localized_view",
            Base.metadata,
            sa.select(  # Build your join query here
                # ...
            )
        )
    
    if TYPE_CHECKING:
        # Don't know if this type checking branch is necessary here.
        # You may want to play around with it.
        id: Mapped[int] = mapped_column(primary_key=True)
        name: Mapped[str] = mapped_column()


    def __repr__(self):
        return f"LocalizedName({self.id!r}, {self.name!r})"

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745607865a4635775.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信