Skip to content

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

strawberry relationship

Tip

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