Model Types =========== What do we mean when we say types? In a Grapple context, a type is a descriptor function that instructs Grapple what type a Django model field is represented by in GraphQL. The field types below are simple to use and all work in the same way. We created a number of built-in types for general use, but you can create your own using `Graphene `_ (Grapple's underlying library) and take advantage of Grapple's generic ``GraphQLField`` type. GraphQLField ------------- .. module:: grapple.models .. class:: GraphQLField(field_name: str, field_type: type = None, required=None, **kwargs) .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: field_type (type) A Grapple model type such as ``GraphQLString`` or ``GraphQLBoolean``. .. attribute:: required (bool=None) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself. If used within a `StreamField`, the method will receive all values from the instance via the `values` kwarg, e.g.: .. code-block:: python class SomeStructBlock(blocks.StructBlock): text = blocks.CharBlock() graphql_fields = [ GraphQLField( field_name="some_name", field_type=graphene.String, source="some_method", ) ] def some_method(self, values: Dict[str, Any] = None) -> Optional[str]: return values.get("text") if values else None GraphQLString ------------- .. module:: grapple.models .. class:: GraphQLString(field_name, required=False, **kwargs) A basic field type is string. Commonly used for CharField, TextField, UrlField or any other Django field that returns a string as it's value. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself. If used within a `StreamField`, the method will receive all values from the instance via the `values` kwarg, e.g.: .. code-block:: python class SomeStructBlock(blocks.StructBlock): text = blocks.CharBlock() graphql_fields = [ GraphQLString( field_name="some_name", source="some_method", ) ] def some_method(self, values: Dict[str, Any] = None) -> Optional[str]: return values.get("text") if values else None In your models.py: .. code-block:: python from grapple.types import GraphQLString class BlogPage(Page): author = models.CharField(max_length=255) graphql_fields = [ GraphQLString("author"), ] Example query: :: query { page(slug: "example-blog-page") { author } } GraphQLCollection ----------------- .. module:: grapple.models .. class:: GraphQLCollection(nested_type, field_name, *args, is_queryset=False, is_paginated_queryset=False, required=False, item_required=False, **kwargs) A field type that wraps another model type in a list. Best suited for referencing Orderables (i.e. ForeignKey lists). .. attribute:: nested_type A Grapple model type such as ``GraphQLString`` or ``GraphQLForeignKey``. .. attribute:: field_name (str) The name of the class property used in your model definition. .. attribute:: *args Any positional arguments that you want to pass on to the nested type. .. attribute:: is_queryset (bool=False) This sets the arguments ``id``, ``limit``, ``offset``, ``search_query``, and ``order`` on the field. .. attribute:: is_paginated_queryset (bool=False) This sets the arguments ``id``, ``page``, ``per_page``, ``search_query``, and ``order`` on the field. Also sets the return value as an extended PaginatedType (example below). .. attribute:: required (bool=False) Represents the list as non-nullable in the schema. This promises the client that an array will be returned. .. attribute:: item_required (bool=False) Represents the fields in the list as non-nullable in the schema. This promises the client that the array items won't be null. .. attribute:: **kwargs Any keyword arguments that you want to pass on to the nested type. One keyword argument that is more powerful with Collections is the ``source`` argument. With ``GraphQLCollection``, You can pass a source string that is multiple layers deep and Grapple will handle the querying for you through multiple models (example below). In your models.py: .. code-block:: python from grapple.types import GraphQLString class BlogPage(Page): author = models.CharField(max_length=255) def paginated_related_links(self, info, **kwargs): return resolve_paginated_queryset(self.related_links.all(), info, **kwargs) graphql_fields = [ # Basic reference to Orderable model GraphQLCollection( GraphQLForeignKey, "related_links", "home.BlogPageRelatedLink" ), # Will return an array of just the url from each link GraphQLCollection(GraphQLString, "related_urls", source="related_links.url"), # Reference to Orderable model with pagination GraphQLCollection( GraphQLForeignKey, "paginated_related_links", "home.BlogPageRelatedLink", is_paginated_queryset=True, ), ] Example query: :: query { page(slug: "example-blog-page") { relatedUrls relatedLinks { name } paginatedRelatedLinks { items { name } pagination { total count perPage currentPage prevPage nextPage totalPages } } } } GraphQLInt ---------- .. module:: grapple.models .. class:: GraphQLInt(field_name, required=False, **kwargs) Used to serialize integer-based Django fields such as ``IntegerField`` or ``PositiveSmallIntegerField``. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself. If used within a `StreamField`, the method will receive all values from the instance via the `values` kwarg, e.g.: .. code-block:: python class SomeStructBlock(blocks.StructBlock): integer = blocks.IntegerBlock() graphql_fields = [ GraphQLInt( field_name="some_name", source="some_method", ) ] def some_method(self, values: Dict[str, Any] = None) -> Optional[int]: return values.get("integer") if values else None GraphQLFloat ------------ .. module:: grapple.models .. class:: GraphQLFloat(field_name, required=False, **kwargs) Like ``GraphQLInt``, this field is used to serialize ``Float`` and ``Decimal`` fields. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself. If used within a `StreamField`, the method will receive all values from the instance via the `values` kwarg, e.g.: .. code-block:: python class SomeStructBlock(blocks.StructBlock): float = blocks.FloatBlock() graphql_fields = [ GraphQLFloat( field_name="some_name", source="some_method", ) ] def some_method(self, values: Dict[str, Any] = None) -> Optional[float]: return values.get("decimal") if values else None GraphQLBoolean -------------- .. module:: grapple.models .. class:: GraphQLBoolean(field_name, required=False, **kwargs) Used to serialize ``Boolean`` fields. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself. If used within a `StreamField`, the method will receive all values from the instance via the `values` kwarg, e.g.: .. code-block:: python class SomeStructBlock(blocks.StructBlock): text = blocks.CharBlock() graphql_fields = [ GraphQLBoolean( field_name="some_name", source="some_method", ) ] def some_method(self, values: Dict[str, Any] = None) -> Optional[bool]: return bool(values.get("text")) if values else None GraphQLStreamfield ------------------ .. module:: grapple.models .. class:: GraphQLStreamfield(field_name, **kwargs) This field type supports all built-in ``Streamfield`` blocks. It also supports custom blocks built using ``StructBlock`` and the like. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Keyword arguments to pass to the field type definition. Notably: * is_list (bool=True) Defaults to True to indicate a list of blocks. Set this to false when the nested ``StructBlock``s do not return a value. e.g. .. code-block:: python @register_streamfield_block class ButtonBlock(blocks.StructBlock): button_text = blocks.CharBlock(required=True, max_length=50, label="Text") button_link = blocks.CharBlock(required=True, max_length=255, label="Link") graphql_fields = [GraphQLString("button_text"), GraphQLString("button_link")] @register_streamfield_block class TextAndButtonsBlock(blocks.StructBlock): text = blocks.TextBlock() buttons = blocks.ListBlock(ButtonBlock()) mainbutton = ButtonBlock() graphql_fields = [ GraphQLString("text"), GraphQLImage("image"), GraphQLStreamfield("buttons"), GraphQLStreamfield( "mainbutton", is_list=False ), # this is a direct StructBlock, not a list of sub-blocks ] @register_paginated_query_field("blog_page") class BlogPage(Page): body = StreamField( [ ("text_and_buttons", TextAndButtonsBlock()), ] ) graphql_fields = [GraphQLStreamfield("body")] :: # Example query, based on the above { blogPage(id: 123) { body { ... on TextAndButtonsBlock { mainbutton { ... on ButtonBlock { buttonText buttonLink } } buttons { ... on ButtonBlock { buttonText buttonLink } } } } } } GraphQLSnippet -------------- .. module:: grapple.models .. class:: GraphQLSnippet(field_name, snippet_model, required=False) ``GraphQLSnippet`` is a little bit more complicated; You first need to define a ``graphql_field`` list on your snippet like you do your page. Then you need to reference the snippet in the field type function. Your snippet values are then available through a sub-selection query on the field name. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: snippet_model (str) String which defines the location of the snippet model. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. In your models.py: .. code-block:: python class BookPage(Page): advert = models.ForeignKey( "demo.Advert", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) graphql_fields = [ GraphQLSnippet("advert", "demo.Advert"), ] content_panels = Page.content_panels + [ SnippetChooserPanel("advert"), ] @register_snippet class Advert(models.Model): url = models.URLField(null=True, blank=True) text = models.CharField(max_length=255) graphql_fields = [ GraphQLString("url"), GraphQLString("text"), ] panels = [ FieldPanel("url"), FieldPanel("text"), ] def __str__(self): return self.text :: # Example query { page(slug: "some-blog-page") { advert { url text } } } GraphQLForeignKey ----------------- .. module:: grapple.models .. class:: GraphQLForeignKey(field_name, content_type, required=False) ``GraphQLForeignKey`` is similar to ``GraphQLSnippet`` in that you pass a ``field_name`` and ``content_type``. You can also specify that the field is a list (for example when using ``Orderable``). For foreign keys to ``wagtailcore.Page``, use ``GraphQLPage``. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: content_type (str) String which defines the location of the model you are referencing. You can also pass the model class itself. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. code-block:: python class BookPage(Page): advert = models.ForeignKey( "demo.Advert", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) graphql_fields = [ GraphQLSnippet("advert", "demo.Advert"), ] content_panels = Page.content_panels + [ SnippetChooserPanel("advert"), ] GraphQLImage ------------ .. module:: grapple.models .. class:: GraphQLImage(field_name, required=False) Use this field type to serialize the core Wagtail or your custom Image model. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. GraphQLDocument --------------- .. module:: grapple.models .. class:: GraphQLDocument(field_name, required=False) Use this field type to serialize the core Wagtail or your custom Document model. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. GraphQLPage ----------- .. module:: grapple.models .. class:: GraphQLPage(field_name: str, **kwargs) Use this field type to serialize a relationship to a Wagtail Page or Page-derived model. The resulting type is the generic Wagtail Page type. A useful type for foreign keys that are not limited to a single, custom Page model, registered with Grapple. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the model itself. It can also be several layers deep and Grapple will handle the querying for you through multiple models. GraphQLTag ----------- .. module:: grapple.models .. class:: GraphQLTag(field_name: str, **kwargs) Use this field type to serialize a ``ClusterTaggableManager`` field. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. GraphQLRichText --------------- .. module:: grapple.models .. class:: GraphQLRichText(field_name, required=False, **kwargs) Use this field type to serialize ``RichTextField`` and ``RichTextBlock`` values. If your :ref:`RICHTEXT_FORMAT` setting is ``"html"``, the stored value will be transformed from the internal representation to proper html. If set to ``"raw"``, the raw internal representation will be returned. .. attribute:: field_name (str) This is the name of the class property used in your model definition. .. attribute:: required (bool=False) Represents the field as non-nullable in the schema. This promises the client that it will have a value returned. .. attribute:: kwargs Useful keyword arguments: * ``description`` (string) A description of the type to show in the GraphiQL browser. * ``deprecation_reason`` (string) Provide a deprecation reason for the Field, will also show in the GraphiQL browser. * ``source`` (string) You can pass a source string that is an attribute or method on the class itself.