Relationships
Linking two models is straightforward with GraftQL: declare a Dl attribute and specify which fields in the current table map to the related table.
It works much like a foreign key in a conventional database.
class Teacher(GraftModel, table=True):
__filter_attributes__ = {"id": {"required": False}}
id: int | None = Field(primary_key=True, default=None)
name: str
# Dl(source=...) points to this model's key field(s), Dl(target=...) points to
# the related model field(s) that should match.
courses: list["Course"] = Dl(source="id", target="teacher_id")
class Course(GraftModel, table=True):
id: int | None = Field(primary_key=True, default=None)
name: str
students: list["StudentCourse"] = Dl(source="id", target="course_id")
teacher_id: int
teacher: "Teacher" = Dl(source="teacher_id", target="id")
In this case the relationship Teacher -> Course will be done using field teacher_id of Course and field id of Teacher.
Note
As the relationship Teacher -> Course is 1 -> N, in this case we use list['TargetClass'] as type hint.
Source and Target parameters can receive a list too, this is useful when you have tables that need many keys to be linked, for example:
class StudentCourse(GraftModel, table=True):
student_id: int = Field(primary_key=True)
course_id: int = Field(primary_key=True)
student: "Student" = Dl(source="student_id", target="id")
course: "Course" = Dl(source="course_id", target="id")
grader: list["Grade"] = Dl(
source=["student_id", "course_id"],
target=["student_id", "course_id"],
)
class Grade(GraftModel, table=True):
student_id: int = Field(primary_key=True)
course_id: int = Field(primary_key=True)
grade: float
semester: int = Field(primary_key=True)
student_course: "StudentCourse" = Dl(
source=["student_id", "course_id"],
target=["student_id", "course_id"],
)
Tip
If you want use a static string or number to make the link between two models, you can pass the string with _ prefix or the number in source and target. Ex: some_field: 'SomeClass' = Dl(source=['some_field', 12, '_staticstring'], target=['target_field', 'month', 'category'])
Here GraftQL will search for a row of SomeClass that has:
source_table.some_field == target_table.target_field
target_table.month == 12
target_table.category == 'staticstring'
Run query
Now in our debugger we can see nested schemas

Tip
Nested fields have their own filters, which work the same way as the top-level query filters.