]> git.ipfire.org Git - thirdparty/fastapi/sqlmodel.git/commitdiff
🐛 Fix SQLAlchemy version 1.4.36 breaks SQLModel relationships (#315) (#461)
authorbyrman <carsten.byrman@nelen-schuurmans.nl>
Sun, 22 Oct 2023 12:01:51 +0000 (14:01 +0200)
committerGitHub <noreply@github.com>
Sun, 22 Oct 2023 12:01:51 +0000 (16:01 +0400)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
sqlmodel/main.py
tests/test_main.py

index 5b5950a811d5a8b7dc770ee4a7a9c89afa08fa38..caae8cf08db606b5ce946f69e6008c9a3b944b15 100644 (file)
@@ -333,6 +333,7 @@ class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta):
                     # There's a SQLAlchemy relationship declared, that takes precedence
                     # over anything else, use that and continue with the next attribute
                     dict_used[rel_name] = rel_info.sa_relationship
+                    setattr(cls, rel_name, rel_info.sa_relationship)  # Fix #315
                     continue
                 ann = cls.__annotations__[rel_name]
                 temp_field = ModelField.infer(
index 22c62327da89c67a735d87def54b76d3f9d8a599..72465cda33015762ae5c298c3531a4a7c9e6886d 100644 (file)
@@ -1,8 +1,9 @@
-from typing import Optional\r
+from typing import List, Optional\r
 \r
 import pytest\r
 from sqlalchemy.exc import IntegrityError\r
-from sqlmodel import Field, Session, SQLModel, create_engine\r
+from sqlalchemy.orm import RelationshipProperty\r
+from sqlmodel import Field, Relationship, Session, SQLModel, create_engine\r
 \r
 \r
 def test_should_allow_duplicate_row_if_unique_constraint_is_not_passed(clear_sqlmodel):\r
@@ -91,3 +92,37 @@ def test_should_raise_exception_when_try_to_duplicate_row_if_unique_constraint_i
             session.add(hero_2)\r
             session.commit()\r
             session.refresh(hero_2)\r
+\r
+\r
+def test_sa_relationship_property(clear_sqlmodel):\r
+    """Test https://github.com/tiangolo/sqlmodel/issues/315#issuecomment-1272122306"""\r
+\r
+    class Team(SQLModel, table=True):\r
+        id: Optional[int] = Field(default=None, primary_key=True)\r
+        name: str = Field(unique=True)\r
+        heroes: List["Hero"] = Relationship(  # noqa: F821\r
+            sa_relationship=RelationshipProperty("Hero", back_populates="team")\r
+        )\r
+\r
+    class Hero(SQLModel, table=True):\r
+        id: Optional[int] = Field(default=None, primary_key=True)\r
+        name: str = Field(unique=True)\r
+        team_id: Optional[int] = Field(default=None, foreign_key="team.id")\r
+        team: Optional[Team] = Relationship(\r
+            sa_relationship=RelationshipProperty("Team", back_populates="heroes")\r
+        )\r
+\r
+    team_preventers = Team(name="Preventers")\r
+    hero_rusty_man = Hero(name="Rusty-Man", team=team_preventers)\r
+\r
+    engine = create_engine("sqlite://", echo=True)\r
+\r
+    SQLModel.metadata.create_all(engine)\r
+\r
+    with Session(engine) as session:\r
+        session.add(hero_rusty_man)\r
+        session.commit()\r
+        session.refresh(hero_rusty_man)\r
+        # The next statement should not raise an AttributeError\r
+        assert hero_rusty_man.team\r
+        assert hero_rusty_man.team.name == "Preventers"\r