Unions
In this section, we'll cover how GraphQL Unions work in Undine.
Unions are abstract GraphQL types that represent a group of ObjectTypes
that need to be returned together, e.g. for a search result.
UnionType
In Undine, a GraphQL Union between two or more QueryTypes
is implemented using a UnionType
.
| from undine import QueryType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType]): ...
|
A UnionType
can be added to a schema using an Entrypoint
.
Note that UnionType
should always be added using a list Entrypoint
(e.g. many=True
).
| from undine import Entrypoint, QueryType, RootType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType]): ...
class Query(RootType):
search_objects = Entrypoint(SearchObjects, many=True)
|
This Entrypoint
can be queried like this:
| query {
searchObjects {
__typename
... on TaskType {
name
}
... on ProjectType {
name
}
}
}
|
Filtering
By default, the an Entrypoint
for a UnionType
will return all instances of all QueryTypes
it contains.
However, if those QueryTypes
implement a FilterSet
or an
OrderSet
, those will also be available on the UnionType
Entrypoint
.
| from undine import Entrypoint, FilterSet, OrderSet, QueryType, RootType, UnionType
from .models import Project, Task
class TaskFilterSet(FilterSet[Task]): ...
class TaskOrderSet(OrderSet[Task]): ...
class TaskType(QueryType[Task], filterset=TaskFilterSet, orderset=TaskOrderSet): ...
class ProjectFilterSet(FilterSet[Project]): ...
class ProjectOrderSet(OrderSet[Project]): ...
class ProjectType(QueryType[Project], filterset=ProjectFilterSet, orderset=ProjectOrderSet): ...
class SearchObjects(UnionType[TaskType, ProjectType]): ...
class Query(RootType):
search_objects = Entrypoint(SearchObjects, many=True)
|
This creates the following Entrypoint
:
| type Query {
searchObjects(
filterTask: TaskFilterSet
orderByTask: [TaskOrderSet!]
filterProject: ProjectFilterSet
orderByProject: [ProjectOrderSet!]
): [Commentable!]!
}
|
This allows filtering and ordering the different types of models in the UnionType
separately.
To filter and order across different models in the UnionType
, you can implement
a FilterSet
or an OrderSet
for the same models as the UnionType
and add it to the UnionType
.
| from undine import Entrypoint, FilterSet, OrderSet, QueryType, RootType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjectsFilterSet(FilterSet[Task, Project]): ...
class SearchObjectsOrderSet(OrderSet[Task, Project]): ...
class SearchObjects(
UnionType[TaskType, ProjectType],
filterset=SearchObjectsFilterSet,
orderset=SearchObjectsOrderSet,
): ...
class Query(RootType):
search_objects = Entrypoint(SearchObjects, many=True)
|
This creates the following Entrypoint
:
| type Query {
searchObjects(
filter: SearchObjectsFilterSet
orderBy: [SearchObjectsOrderSet!]
): [Commentable!]!
}
|
Note that a FilterSet
or OrderSet
created for multiple models like this
should only contain Filters
and Orders
which will work on all models in the UnionType
,
i.e. they are of the same type.
To paginate UnionTypes
, you can use the Connection
Entrypoint
.
| from undine import Entrypoint, QueryType, RootType, UnionType
from undine.relay import Connection
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType]): ...
class Query(RootType):
search_objects = Entrypoint(Connection(SearchObjects))
|
See the Pagination section for more details on pagination.
Schema name
By default, the name of the generated GraphQL Union
is the same as the name of the UnionType
class.
If you want to change the name, you can do so by setting the schema_name
argument:
| from undine import QueryType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType], schema_name="Search"): ...
|
Description
A description for a UnionType
can be provided as a docstring.
| from undine import QueryType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType]):
"""Description"""
|
GraphQL Extensions
You can provide custom extensions for the UnionType
by providing a
extensions
argument with a dictionary containing them.
| from undine import QueryType, UnionType
from .models import Project, Task
class TaskType(QueryType[Task]): ...
class ProjectType(QueryType[Project]): ...
class SearchObjects(UnionType[TaskType, ProjectType], extensions={"foo": "bar"}): ...
|
UnionType
extensions are made available in the GraphQL UnionType
extensions
after the schema is created. The UnionType
itself is found in the extensions
under a key defined by the UNION_TYPE_EXTENSIONS_KEY
setting.