Schema🔗
In this section, we'll cover how you can set up entrypoints to you GraphQL schema in Undine, expanding on the basics introduced in the Tutorial.
RootTypes🔗
A GraphQL schema defines a RootType
for each kind of operation that it supports.
In GraphQL terms, a RootType
is just a regular ObjectType
that just happens
to be the root of the GraphQL Schema.
Let's take a look at the basic setup from the Tutorial.
Here you created the Query
RootType
. The Query
RootType
is
required to be able to crate a GraphQL schema. Each RootType
must also have at
least one Entrypoint
in its class body.
As the name implies, the Query
RootType
is for querying data.
For mutating data, you'd create a Mutation
RootType
.
The Mutation
RootType
is optional, but if created, it must also include at least
one Entrypoint
, just like the Query
RootType
.
What about Subscriptions
?
Undine does not support have support for subscriptions, but it's on the roadmap.
Schema name🔗
By default, the name of the RootType
type is the name of the created class.
If you need to change this without changing the class name,
you can do so by providing the schema_name
argument.
Description🔗
To provide a description for the RootType
, you can add a docstring to the class.
Directives🔗
You can add directives to the RootType
by providing them using the directives
argument.
See the Directives section for more details on directives.
GraphQL extensions🔗
You can provide custom extensions for the RootType
by providing a
extensions
argument with a dictionary containing them. These can then be used
however you wish to extend the functionality of the RootType
.
RootType
extensions are made available in the GraphQL ObjectType
extensions
after the schema is created. The RootType
itself is found in the extensions
under a key defined by the ROOT_TYPE_EXTENSIONS_KEY
setting.
Entrypoints🔗
Entrypoints
can be thought of as the "API endpoints inside the GraphQL schema".
They are the fields in a RootType
from which you can execute operations like queries
or mutations.
An Entrypoint
always requires a reference from which it will create the
proper GraphQL resolver, output type, and arguments for the operation.
Function references🔗
Using a function/method as a reference is the most basic way of creating an Entrypoint
.
Function references can be used for both query and mutation Entrypoints
.
See the example from the Tutorial.
With a function reference, the Entrypoint
will use the decorated function as its GraphQL resolver.
The function's return type will be used as the Entrypoint's
output type, so typing it is required.
You can even use a TypedDict to return an object with multiple fields.
About method signature
A method decorated with @Entrypoint
is treated as a static method by the Entrypoint
.
The self
argument is not an instance of the RootType
,
but root
argument of the GraphQLField
resolver. To clarify this,
it's recommended to change the argument's name to root
,
as defined by the RESOLVER_ROOT_PARAM_NAME
setting.
The value of the root
argument for an Entrypoint
is None
by default,
but can be configured using the ROOT_VALUE
setting if desired.
The info
argument can be left out, but if it's included, it should always
have the GQLInfo
type annotation.
You can add arguments to the Entrypoint
by adding them to the function signature.
Typing these arguments is required to determine their input type.
This will add a non-null name
string argument to the Entrypoint
.
Note that non-null arguments are required by GraphQL, so if you wanted to make the argument
optional, you'd need to make it nullable (in which case it will be None
by default)
or add a default value ourselves.
You can add a description to the Entrypoint
by adding a docstring to the method.
If the method has arguments, you can add descriptions to those arguments by using
reStructuredText docstrings format.
What about other docstring formats?
Other types of docstrings can be used by parsed by providing a custom parser to the
DOCSTRING_PARSER
setting that conforms to the
DocstringParserProtocol
from undine.typing
.
QueryType references🔗
A QueryType
represents a GraphQL ObjectType
for querying data from a Django model
in the GraphQL schema. You should read more on QueryTypes
in the Queries section
since this section will only cover using them in Entrypoints
.
For querying a single model instance, simply use the QueryType
class
as the reference for the Entrypoint
.
This would create the following field in the Query
RootType
:
To query a list of model instances, simply add the many
argument
to the Entrypoint
in addition to the QueryType
.
This would create the following field in the Query
RootType
:
MutationType references🔗
A MutationType
represents a possible mutation operation based on a Django model.
You should read more on MutationTypes
in the Mutations section
since this section will only cover using them in Entrypoints
.
To create a mutation for a model instance (a create mutation in this example),
simply use the MutationType
class as the reference for the Entrypoint
.
This would create the following field in the Mutation
RootType
:
To make this a bulk mutation, you can add the many
argument to the Entrypoint
.
This would create the following field in the Mutation
RootType
:
Schema name🔗
By default, the name of the Entrypoint
is the name of the method or class attribute
it's defined in. If you need to change this without changing the method or class attribute name,
for example if the desired name is a Python keyword (e.g. if
or from
),
you can do so by providing the schema_name
argument.
Description🔗
You can provide a description using the description
argument.
You can also provide the description as a "class attribute docstring".
If a description is not provided in these ways, the Entrypoint
will try
to determine a description from the given reference, e.g., for a method
reference, it will use the method's docstring, or for a QueryType
reference,
it will use the QueryType's
docstring.
Many🔗
As seen in this section, the many
argument is used to indicate whether the Entrypoint
should return a non-null list of the referenced type. However, for for function references,
the many
argument is not required, as the Entrypoint
can determine the this
from the function's signature (i.e. whether it returns a list or not).
Nullable🔗
By default, all Entrypoints
are non-null (except for function references,
which determine nullability from the function's signature). However, you can
make an Entrypoint
nullable explicitly by adding the nullable
argument.
Limit🔗
The limit
argument is used by UnionTypes and
InterfaceTypes to limit the number of objects
that are fetched when those types are used in Entrypoints
. It has no effect
on other Entrypoint
references.
Permissions🔗
Usually, permissions for Entrypoints
are checked using the QueryType
or MutationType
that the Entrypoint
is added for. However, you can override these by decorating a method
using the @<entrypoint_name>.permissions
decorator.
Deprecation reason🔗
A deprecation_reason
can be provided to mark the Entrypoint
as deprecated.
This is for documentation purposes only and does not affect the use of the Entrypoint
.
Directives🔗
You can add directives to the Entrypoint
by providing them using the directives
argument.
See the Directives section for more details on directives.
GraphQL extensions🔗
You can provide custom extensions for the Entrypoint
by providing a extensions
argument with a dictionary containing them. These can then be used however you wish to
extend the functionality of the Entrypoint
.
Entrypoint
extensions are made available in the GraphQL field extensions
after the schema is created. The Entrypoint
itself is found in the extensions
under a key defined by the ENTRYPOINT_EXTENSIONS_KEY
setting.