]> git.ipfire.org Git - thirdparty/fastapi/sqlmodel.git/commitdiff
📝 Document `.in_()` method (#619)
authorPau Ramon Revilla <masylum@gmail.com>
Wed, 4 Mar 2026 12:13:04 +0000 (13:13 +0100)
committerGitHub <noreply@github.com>
Wed, 4 Mar 2026 12:13:04 +0000 (13:13 +0100)
* Document IN()

* Update "includes" and "tip" formatting in `where.md`

* Fix code block formatting in `where.md`

* Fix link in `where.md`

* Rename code example, add `_py310` version

---------

Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Yurii Motov <yurii.motov.monte@gmail.com>
docs/tutorial/where.md
docs_src/tutorial/where/tutorial006b_py310.py [new file with mode: 0644]
docs_src/tutorial/where/tutorial006b_py39.py [new file with mode: 0644]
tests/test_tutorial/test_where/test_tutorial006b.py [new file with mode: 0644]

index b6d08e72fa74053d15311374a5ecef5cd73fad71..120874a235fa0b0f4b36e6866e5356c822bc0180 100644 (file)
@@ -562,7 +562,7 @@ We could imagine that **Spider-Boy** is even **younger**. But because we don't k
 
 ### Less Than or Equal
 
-Finally, we can use `<=` to get the rows where a column is **less than or equal** to a value:
+We can also use `<=` to get the rows where a column is **less than or equal** to a value:
 
 {* ./docs_src/tutorial/where/tutorial006_py310.py ln[42:47] hl[44] *}
 
@@ -579,6 +579,22 @@ We get `Black Lion` here too because although the age is not *strictly* less tha
 
 ///
 
+### In
+
+Finally, we can use `in_` to get the rows where a column is a member of a collection of values:
+
+{* ./docs_src/tutorial/where/tutorial006b_py310.py ln[42:47] hl[44] *}
+
+In this case, we match `Deadpond` since it's part of the collections of names.
+We don't have any hero called `Ratman`, so it does not match any hero.
+
+/// tip
+
+You need to wrap your attribute with `col()` to use `in_`.
+You can read more about it in the [Type annotations and errors](#type-annotations-and-errors){.internal-link target=_blank} section.
+
+///
+
 ### Benefits of Expressions
 
 Here's a good moment to see that being able to use these pure Python expressions instead of keyword arguments can help a lot. ✨
diff --git a/docs_src/tutorial/where/tutorial006b_py310.py b/docs_src/tutorial/where/tutorial006b_py310.py
new file mode 100644 (file)
index 0000000..21a4e28
--- /dev/null
@@ -0,0 +1,57 @@
+from sqlmodel import Field, Session, SQLModel, col, create_engine, select
+
+
+class Hero(SQLModel, table=True):
+    id: int | None = Field(default=None, primary_key=True)
+    name: str
+    secret_name: str
+    age: int | None = None
+
+
+sqlite_file_name = "database.db"
+sqlite_url = f"sqlite:///{sqlite_file_name}"
+
+engine = create_engine(sqlite_url, echo=True)
+
+
+def create_db_and_tables():
+    SQLModel.metadata.create_all(engine)
+
+
+def create_heroes():
+    hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
+    hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
+    hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
+    hero_4 = Hero(name="Tarantula", secret_name="Natalia Roman-on", age=32)
+    hero_5 = Hero(name="Black Lion", secret_name="Trevor Challa", age=35)
+    hero_6 = Hero(name="Dr. Weird", secret_name="Steve Weird", age=36)
+    hero_7 = Hero(name="Captain North America", secret_name="Esteban Rogelios", age=93)
+
+    with Session(engine) as session:
+        session.add(hero_1)
+        session.add(hero_2)
+        session.add(hero_3)
+        session.add(hero_4)
+        session.add(hero_5)
+        session.add(hero_6)
+        session.add(hero_7)
+
+        session.commit()
+
+
+def select_heroes():
+    with Session(engine) as session:
+        statement = select(Hero).where(col(Hero.name).in_(["Deadpond", "Ratman"]))
+        results = session.exec(statement)
+        for hero in results:
+            print(hero)
+
+
+def main():
+    create_db_and_tables()
+    create_heroes()
+    select_heroes()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/docs_src/tutorial/where/tutorial006b_py39.py b/docs_src/tutorial/where/tutorial006b_py39.py
new file mode 100644 (file)
index 0000000..deb0b23
--- /dev/null
@@ -0,0 +1,59 @@
+from typing import Optional
+
+from sqlmodel import Field, Session, SQLModel, col, create_engine, select
+
+
+class Hero(SQLModel, table=True):
+    id: Optional[int] = Field(default=None, primary_key=True)
+    name: str
+    secret_name: str
+    age: Optional[int] = None
+
+
+sqlite_file_name = "database.db"
+sqlite_url = f"sqlite:///{sqlite_file_name}"
+
+engine = create_engine(sqlite_url, echo=True)
+
+
+def create_db_and_tables():
+    SQLModel.metadata.create_all(engine)
+
+
+def create_heroes():
+    hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
+    hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
+    hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
+    hero_4 = Hero(name="Tarantula", secret_name="Natalia Roman-on", age=32)
+    hero_5 = Hero(name="Black Lion", secret_name="Trevor Challa", age=35)
+    hero_6 = Hero(name="Dr. Weird", secret_name="Steve Weird", age=36)
+    hero_7 = Hero(name="Captain North America", secret_name="Esteban Rogelios", age=93)
+
+    with Session(engine) as session:
+        session.add(hero_1)
+        session.add(hero_2)
+        session.add(hero_3)
+        session.add(hero_4)
+        session.add(hero_5)
+        session.add(hero_6)
+        session.add(hero_7)
+
+        session.commit()
+
+
+def select_heroes():
+    with Session(engine) as session:
+        statement = select(Hero).where(col(Hero.name).in_(["Deadpond", "Ratman"]))
+        results = session.exec(statement)
+        for hero in results:
+            print(hero)
+
+
+def main():
+    create_db_and_tables()
+    create_heroes()
+    select_heroes()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/test_tutorial/test_where/test_tutorial006b.py b/tests/test_tutorial/test_where/test_tutorial006b.py
new file mode 100644 (file)
index 0000000..237618a
--- /dev/null
@@ -0,0 +1,35 @@
+import importlib
+from types import ModuleType
+
+import pytest
+from sqlmodel import create_engine
+
+from ...conftest import PrintMock, needs_py310
+
+
+@pytest.fixture(
+    name="mod",
+    params=[
+        pytest.param("tutorial006b_py39"),
+        pytest.param("tutorial006b_py310", marks=needs_py310),
+    ],
+)
+def get_module(request: pytest.FixtureRequest) -> ModuleType:
+    mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}")
+    mod.sqlite_url = "sqlite://"
+    mod.engine = create_engine(mod.sqlite_url)
+    return mod
+
+
+def test_tutorial(print_mock: PrintMock, mod: ModuleType):
+    mod.main()
+    assert print_mock.calls == [
+        [
+            {
+                "name": "Deadpond",
+                "secret_name": "Dive Wilson",
+                "age": None,
+                "id": 1,
+            }
+        ]
+    ]