### Install Wagtail Grapple with Pip Source: https://github.com/torchbox/wagtail-grapple/wiki/02:-Installation Installs the wagtail_grapple library using pip. This is the initial step for integrating the library into your project. ```shell pip install wagtail_grapple ``` -------------------------------- ### Install and Configure Wagtail Grapple Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Basic installation instructions and project setup for Wagtail Grapple, including adding required Django apps, configuring the Graphene schema, and defining Grapple settings in `settings.py`. It also shows how to include Grapple's URLs in your project's `urls.py`. ```python # Install via pip # pip install wagtail-grapple # settings.py - Add required apps INSTALLED_APPS = [ # ... other apps "grapple", "graphene_django", # ... rest of apps ] # settings.py - Configure Grapple GRAPHENE = {"SCHEMA": "grapple.schema.schema"} GRAPPLE = { "APPS": ["home", "blog"], # Apps to scan for GraphQL models "AUTO_CAMELCASE": True, # Convert field names to camelCase "EXPOSE_GRAPHIQL": True, # Enable GraphiQL interface "PAGE_SIZE": 10, # Default pagination size "MAX_PAGE_SIZE": 100, # Maximum items per page "ADD_SEARCH_HIT": False, # Track search hits in Wagtail "ALLOWED_IMAGE_FILTERS": None, # Restrict image operations "RICHTEXT_FORMAT": "html", # Output format for rich text } # urls.py - Add GraphQL endpoints from django.urls import include, path from grapple import urls as grapple_urls urlpatterns = [ path("api/", include(grapple_urls)), # ... other URL patterns ] # GraphQL endpoint available at: http://localhost:8000/api/graphql/ # GraphiQL IDE available at: http://localhost:8000/api/graphiql/ ``` -------------------------------- ### Configure Installed Apps for Wagtail Grapple Source: https://github.com/torchbox/wagtail-grapple/wiki/02:-Installation Adds necessary applications ('grapple', 'graphene_django', 'channels') to the 'installed_apps' list in your Wagtail settings file. This ensures the library's components are recognized by Django. ```python installed_apps = [ ... "grapple", "graphene_django", "channels", ... ] ``` -------------------------------- ### Configure Grapple Settings Source: https://github.com/torchbox/wagtail-grapple/wiki/02:-Installation Sets up the GraphQL schema and defines which Django apps should be scanned by Grapple for generating GraphQL types. The 'GRAPPLE_APPS' dictionary maps app names to type prefixes. ```python # Grapple Config: GRAPHENE = {"SCHEMA": "grapple.schema.schema"} GRAPPLE_APPS = { "home": "" } ``` -------------------------------- ### Include Grapple URLs in Project URLs Source: https://github.com/torchbox/wagtail-grapple/wiki/02:-Installation Integrates the GraphQL URLs provided by the 'grapple' library into your project's main 'urls.py' file. This makes the GraphQL endpoint accessible. ```python from grapple import urls as grapple_urls ... urlpatterns = [ ... url(r"", include(grapple_urls)), ... ] ``` -------------------------------- ### Project Settings Configuration Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/settings.rst Example of how to configure Wagtail Grapple settings in your Django project's settings.py file. ```APIDOC ## Project Settings Configuration ### Description This section shows how to define the `GRAPPLE` dictionary in your Django `settings.py` file to customize Wagtail Grapple's behavior. ### Method Configuration via Django settings. ### Endpoint Not applicable (Django settings) ### Parameters #### Request Body - **GRAPPLE** (dict) - Required - A dictionary containing various configuration options for Wagtail Grapple. - **APPS** (list[str]) - Optional - A list of Django app names for Grapple to scan for models. - **ADD_SEARCH_HIT** (bool) - Optional - If True, logs search queries for Wagtail's promoted results. - **AUTO_CAMELCASE** (bool) - Optional - If True, converts snake_case field/argument names to camelCase. Defaults to True. - **EXPOSE_GRAPHIQL** (bool) - Optional - If True, exposes the GraphiQL interface at `/graphiql`. Defaults to False. - **ALLOWED_IMAGE_FILTERS** (list[str]) - Optional - A list of allowed image transformation filters for renditions. Defaults to None. - **RICHTEXT_FORMAT** (str) - Optional - Controls the output format for RichText fields and blocks. Can be 'html' or 'raw'. Defaults to 'html'. - **PAGE_SIZE** (int) - Optional - Default page size for pagination. Defaults to 10. - **MAX_PAGE_SIZE** (int) - Optional - Maximum allowed page size for pagination. Defaults to 100. - **PAGE_INTERFACE** (str) - Optional - The GraphQL interface used for Wagtail Page models. Defaults to 'grapple.types.interfaces.PageInterface'. - **SNIPPET_INTERFACE** (str) - Optional - The GraphQL interface used for Wagtail snippet models. Defaults to 'grapple.types.interfaces.SnippetInterface'. ### Request Example ```python # settings.py GRAPPLE = { "APPS": ["home", "blog"], "ADD_SEARCH_HIT": True, "EXPOSE_GRAPHIQL": True, "ALLOWED_IMAGE_FILTERS": [ "width-1000", "fill-300x150|jpegquality-60", "width-700|format-webp", ], "RICHTEXT_FORMAT": "raw", "PAGE_SIZE": 20, "MAX_PAGE_SIZE": 200, } ``` ### Response N/A (Configuration setting) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Install Wagtail Grapple via Pip Source: https://github.com/torchbox/wagtail-grapple/blob/main/README.md This command installs the wagtail-grapple package using pip. Ensure you have Python and pip installed and configured correctly. ```bash python -m pip install wagtail_grapple ``` -------------------------------- ### Configure INSTALLED_APPS for Wagtail Grapple Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/installation.rst Adds 'grapple' and 'graphene_django' to the INSTALLED_APPS list in your Wagtail settings. This enables the library's functionalities within your project. Ensure these are included before other Django apps that might rely on them. ```python INSTALLED_APPS = [ # ... "grapple", "graphene_django", # ... ] ``` -------------------------------- ### GraphQL Query for BlogPage Data Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/examples.rst An example GraphQL query to retrieve specific fields from the 'BlogPage' type, demonstrating how to access nested fields within the 'body' StreamField. ```graphql query { pages { ...on BlogPage { heading date author summary body { rawValue ...on ImageBlock { image { src } decorative altText } } } } } ``` -------------------------------- ### Configure Wagtail Grapple Settings Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/settings.rst Example of how to configure Wagtail Grapple settings in a Django project's settings.py file. This includes defining the apps to scan and other feature flags. ```python # settings.py GRAPPLE = { "APPS": ["home"], "ADD_SEARCH_HIT": True, # ... } ``` -------------------------------- ### Query All Sites Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Provides an example of querying all available sites using the plural `sites` field on the root query type, retrieving basic site information. ```graphql query { sites { port hostname siteName } } ``` -------------------------------- ### Configure GRAPHENE and GRAPPLE settings Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/installation.rst Sets up the GraphQL schema and defines the apps to be scanned by Grapple. The GRAPHENE setting points to the schema file, while GRAPPLE's APPS list specifies which Wagtail apps should have their models exposed as GraphQL types. This configuration is crucial for Grapple to generate your GraphQL schema. ```python # Grapple Config: GRAPHENE = {"SCHEMA": "grapple.schema.schema"} GRAPPLE = { "APPS": ["home"], } ``` -------------------------------- ### Query Pages within a Site Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Provides an example of fetching multiple pages within a specific site, with options for limiting, offsetting, and ordering results. ```graphql query { site(hostname: "my.domain.com") { pages(limit: 10, offset: 0, order: "-first_published_at") { title slug } } } ``` -------------------------------- ### Include Grapple URLs in Django project Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/installation.rst Integrates the Grapple GraphQL URLs into your main Django project's URL configuration. This makes your GraphQL endpoint accessible at the root path. Remember to import 'grapple.urls' and include it in your urlpatterns. ```python from django.urls import path from grapple import urls as grapple_urls # ... urlpatterns = [ # ... path("", include(grapple_urls)), # ... ] ``` -------------------------------- ### Defining a Custom GraphQL Interface Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/interfaces.rst Provides a Python code example using Graphene to define a custom GraphQL interface named 'MyInterface', which can then be applied to Wagtail models. ```python import graphene class MyInterface(graphene.Interface): ``` -------------------------------- ### Configure Allowed Image Rendition Filters Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/settings.rst Example of setting specific image filters allowed by Wagtail Grapple to prevent arbitrary rendition generation. This is done within the GRAPPLE settings. ```python # settings.py GRAPPLE = { # ... "ALLOWED_IMAGE_FILTERS": [ "width-1000", "fill-300x150|jpegquality-60", "width-700|format-webp", ] } ``` -------------------------------- ### GraphQL Query Example for Streamfield Data Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/model-types.rst An example GraphQL query demonstrating how to fetch data from a StreamField that uses nested blocks, specifically TextAndButtonsBlock and ButtonBlock, including fragment matching for specific block types. ```graphql { blogPage(id: 123) { body { ... on TextAndButtonsBlock { mainbutton { ... on ButtonBlock { buttonText } } } } } } ``` -------------------------------- ### GraphQL Query Example for Author Field Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/model-types.rst An example GraphQL query to retrieve the 'author' field from a 'page' object. This demonstrates how a client would interact with a schema that includes the GraphQLString type for the author field. ```graphql query { page(slug: "example-blog-page") { author } } ``` -------------------------------- ### Custom Middleware for Field Access (Python) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Demonstrates how to implement and apply custom middleware to GraphQL fields in Wagtail Grapple for access control. It includes examples of authentication and premium content checks, showing how to register middleware globally or per field. ```python from grapple.helpers import register_query_field, register_field_middleware from django.db import models from wagtail.models import Page from grapple.models import GraphQLString # Define custom middleware def authentication_middleware(next, root, info, **args): """Check if user is authenticated""" if not info.context.user.is_authenticated: return None return next(root, info, **args) def premium_content_middleware(next, root, info, **args): """Check if user has premium access""" if hasattr(info.context.user, 'has_premium') and info.context.user.has_premium: return next(root, info, **args) return None # Apply middleware to specific fields @register_query_field("premium_article", middleware=[authentication_middleware, premium_content_middleware]) class PremiumArticle(Page): content = models.TextField() graphql_fields = [ GraphQLString("content"), ] # Register middleware for specific field names register_field_middleware("premium_content", [authentication_middleware]) # Query protected content """ query { premiumArticle(id: 5) { title content } } # Returns null if middleware blocks access # Returns data if all middleware checks pass """ ``` -------------------------------- ### Field Descriptions and Deprecation Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Adds descriptive text and deprecation notices to GraphQL fields, improving schema clarity and guiding consumers. ```APIDOC ## Field Descriptions and Deprecation ### Description Add documentation and deprecation notices to GraphQL fields. This helps users understand the purpose of fields and guides them away from deprecated ones. ### Method N/A (Schema definition) ### Endpoint N/A (Schema definition) ### Parameters N/A (Schema definition) ### Request Example N/A (Schema definition) ### Response #### GraphQL Schema Definition with Introspection - **DocumentedPage** (object) - Represents a page with documented and deprecated fields. - **currentField** (String) - The current recommended field for storing data. (Description: The current recommended field for storing data) - **oldField** (String @deprecated(reason: "Use current_field instead. This will be removed in v2.0")) - This field is deprecated and will be removed in a future version. #### Response Example (Schema with Introspection) ```graphql type DocumentedPage { currentField: String # Description: The current recommended field for storing data oldField: String @deprecated(reason: "Use current_field instead. This will be removed in v2.0") } ``` ``` -------------------------------- ### Load Static and Wagtail Userbar Tags Source: https://github.com/torchbox/wagtail-grapple/blob/main/tests/testapp/templates/base.html Loads the static files and Wagtail userbar tags for use within Django templates. This is a common setup for Wagtail projects to enable static asset management and the admin user bar. ```django {% load static wagtailuserbar %} ``` -------------------------------- ### SnippetInterface Query Example Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/interfaces.rst Demonstrates how to query all snippets using the 'snippets' field on the root Query type. Shows how to access default snippet fields and query custom fields from specific snippet types like 'Advert'. ```graphql query { snippets { snippetType contentType ...on Advert { id url text } } } ``` -------------------------------- ### Field Descriptions and Deprecation (Python) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Shows how to add descriptive text and deprecation warnings to GraphQL fields using `description` and `deprecation_reason` arguments in `grapple.models`. This enhances schema discoverability and guides users away from outdated fields. ```python from grapple.models import GraphQLString from wagtail.models import Page from django.db import models class DocumentedPage(Page): current_field = models.CharField(max_length=255) old_field = models.CharField(max_length=255) graphql_fields = [ GraphQLString( "current_field", description="The current recommended field for storing data" ), GraphQLString( "old_field", deprecation_reason="Use current_field instead. This will be removed in v2.0" ), ] # GraphQL introspection shows: """ type DocumentedPage { currentField: String # Description: The current recommended field for storing data oldField: String @deprecated(reason: "Use current_field instead. This will be removed in v2.0") } """ ``` -------------------------------- ### Define GraphQL Fields in Wagtail Model (Python) Source: https://github.com/torchbox/wagtail-grapple/blob/main/README.md This Python example demonstrates how to define GraphQL fields for a Wagtail `BlogPage` model using Grapple. It shows how to annotate fields like 'author', 'date', and 'body' (a StreamField) for GraphQL exposure. ```python # ... from grapple.models import GraphQLString, GraphQLStreamfield class BlogPage(Page): author = models.CharField(max_length=255) date = models.DateField("Post date") body = StreamField( [ ("heading", blocks.CharBlock(classname="full title")), ("paragraph", blocks.RichTextBlock()), ("image", ImageChooserBlock()), ] ) content_panels = Page.content_panels + [ FieldPanel("author"), FieldPanel("date"), StreamFieldPanel("body"), ] # Note these fields below: graphql_fields = [ GraphQLString("heading"), GraphQLString("date"), GraphQLString("author"), GraphQLStreamfield("body"), ] ``` -------------------------------- ### Perform Cross-Model Search (GraphQL) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Illustrates how to perform a search across all registered Wagtail models using the `search` query. The example shows how to use fragments to fetch specific fields based on the `__typename` of the found objects, enabling polymorphic search results. ```graphql query { search(query: "python") { ... on BlogPage { __typename title url author } ... on ContentPage { __typename title url introduction } ... on ImageObjectType { __typename title src } ... on DocumentObjectType { __typename title url } } } ``` -------------------------------- ### Handle Wagtail RichTextField with GraphQL Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Shows how to define and query Wagtail RichTextFields using GraphQL. It includes a Python model definition with `RichTextField` and its corresponding GraphQL type `GraphQLRichText`, along with example queries and responses for both HTML and raw content. ```python from wagtail.models import Page from wagtail.fields import RichTextField from wagtail.admin.panels import FieldPanel from grapple.models import GraphQLString, GraphQLRichText class ContentPage(Page): introduction = RichTextField(blank=True) body = RichTextField() content_panels = Page.content_panels + [ FieldPanel("introduction"), FieldPanel("body"), ] graphql_fields = [ GraphQLString("title"), GraphQLRichText("introduction"), GraphQLRichText("body"), ] ``` ```graphql query { page(id: 5) { ... on ContentPage { title introduction body } } } Response: { "data": { "page": { "title": "About Us", "introduction": "

Welcome to our company.

", "body": "

Our Mission

We strive to deliver excellent solutions.

" } } } ``` -------------------------------- ### Query Wagtail Pages by ID, Slug, or URL in GraphQL Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Shows basic GraphQL queries to retrieve Wagtail pages. It covers fetching a single page by its unique ID, slug, or URL path. The example also demonstrates how to filter pages based on their site using the `inSite` argument, returning common page fields like title, slug, and URL. ```graphql # Query single page by ID query { page(id: 3) { title slug url pageType contentType seoTitle searchDescription } } # Query page by slug query { page(slug: "contact") { title lastPublishedAt firstPublishedAt } } # Query page by URL path query { page(urlPath: "/blog/my-post/") { title url } } # Query page with site filtering query { page(slug: "homepage", inSite: true) { title url } } ``` -------------------------------- ### Implement and Query Paginated Results (Python/GraphQL) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Shows how to register custom paginated query fields for Wagtail models using the `register_paginated_query_field` decorator. It includes examples of querying paginated results with both limit/offset and page/perPage parameters, along with accessing pagination metadata. ```python from grapple.helpers import register_paginated_query_field from wagtail.models import Page @register_paginated_query_field("blogPost") class BlogPostPage(Page): # ... field definitions pass # Paginated query with limit and offset """ query { blogPosts(limit: 10, offset: 0, order: "-first_published_at") { items { title url firstPublishedAt } pagination { total count perPage currentPage prevPage nextPage totalPages } } } """ # Query specific page of results """ query { blogPosts(page: 2, perPage: 20) { items { title } pagination { currentPage totalPages } } } """ ``` -------------------------------- ### PageInterface Fields and Query Example Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/interfaces.rst Defines the default GraphQL interface for Wagtail Page models, exposing fields like id, url, title, and hierarchical relationships. Also shows how to query custom fields using the spread operator with a specific Page type. ```graphql query { pages { ...on BlogPage { the_custom_field } } } ``` -------------------------------- ### GraphiQL Initialization and Fetcher Logic (JavaScript) Source: https://github.com/torchbox/wagtail-grapple/blob/main/grapple/templates/grapple/graphiql.html This snippet initializes the GraphiQL interface, parses URL parameters to configure the GraphQL endpoint and subscription endpoint, and defines a fetcher function for executing GraphQL queries. It handles both standard fetch requests and WebSocket-based subscriptions. ```javascript var parameters = {}; window.location.search.substr(1).split('&').forEach(function (entry) { var eq = entry.indexOf('='); if (eq >= 0) { parameters[decodeURIComponent(entry.slice(0, eq))] = decodeURIComponent(entry.slice(eq + 1)); } }); function locationQuery(params, location) { return (location ? location : '') + '?' + Object.keys(params).map(function (key) { return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]); }).join('&'); } var graphqlParamNames = { query: true, variables: true, operationName: true }; var otherParams = {}; for (var k in parameters) { if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) { otherParams[k] = parameters[k]; } } var fetcher; var supports_subscriptions = {{ supports_subscriptions|lower }}; if (supports_subscriptions) { var subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('{{subscriptionsEndpoint}}', { reconnect: true }); fetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher); } else { fetcher = graphQLFetcher; } var fetchURL = locationQuery(otherParams, '{{endpointURL}}'); function graphQLFetcher(graphQLParams) { return fetch(fetchURL, { method: 'post', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify(graphQLParams), credentials: 'include', }).then(function (response) { return response.text(); }).then(function (responseBody) { try { return JSON.parse(responseBody); } catch (error) { return responseBody; } }); } function onEditQuery(newQuery) { parameters.query = newQuery; updateURL(); } function onEditVariables(newVariables) { parameters.variables = newVariables; updateURL(); } function onEditOperationName(newOperationName) { parameters.operationName = newOperationName; updateURL(); } function updateURL() { history.replaceState(null, null, locationQuery(parameters) + window.location.hash); } ReactDOM.render( React.createElement(GraphiQL, { fetcher: fetcher, onEditQuery: onEditQuery, onEditVariables: onEditVariables, onEditOperationName: onEditOperationName, }), document.getElementById('graphiql') ); ``` -------------------------------- ### Expose Wagtail Images and Documents via GraphQL Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Demonstrates how to integrate Wagtail's Image and Document models into a GraphQL API using `GraphQLImage` and `GraphQLDocument`. It covers defining the models, setting up content panels, and querying fields like `src`, `url`, `fileSize`, and `createdAt`. ```python from django.db import models from wagtail.models import Page from wagtail.images import get_image_model from wagtail.documents import get_document_model from wagtail.admin.panels import FieldPanel from grapple.models import GraphQLString, GraphQLImage, GraphQLDocument class MediaPage(Page): featured_image = models.ForeignKey( get_image_model(), null=True, blank=True, on_delete=models.SET_NULL, related_name="+" ) pdf_document = models.ForeignKey( get_document_model(), null=True, blank=True, on_delete=models.SET_NULL, related_name="+" ) content_panels = Page.content_panels + [ FieldPanel("featured_image"), FieldPanel("pdf_document"), ] graphql_fields = [ GraphQLString("title"), GraphQLImage("featured_image"), GraphQLDocument("pdf_document"), ] ``` ```graphql query { page(slug: "media-page") { ... on MediaPage { title featuredImage { src url width height aspectRatio sizes alt } pdfDocument { url file fileSize fileHash createdAt } } } } Response: { "data": { "page": { "title": "Media Gallery", "featuredImage": { "src": "/media/images/hero.original.jpg", "url": "/media/images/hero.jpg", "width": 1920, "height": 1080, "aspectRatio": 1.777, "sizes": "(max-width: 1920px) 100vw, 1920px", "alt": "Hero image" }, "pdfDocument": { "url": "/media/documents/whitepaper.pdf", "file": "documents/whitepaper.pdf", "fileSize": 2048576, "fileHash": "abc123def456", "createdAt": "2025-01-01T12:00:00Z" } } } } ``` -------------------------------- ### Query Pages with Filtering, Ordering, and Pagination (GraphQL) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Demonstrates how to query multiple pages using various filters like content type, parent/ancestor, menu inclusion, and search terms. It also shows how to order results and use pagination with limits and offsets. This functionality is primarily used with GraphQL clients. ```graphql query { pages(contentType: "blog.BlogPage", order: "-first_published_at") { title url firstPublishedAt ... on BlogPage { author publishDate } } } query { pages(contentType: "blog.BlogPage,news.NewsPage") { title pageType } } query { pages(parent: 2) { title slug } } query { pages(ancestor: 5, limit: 10, offset: 0) { title depth } } query { pages(searchQuery: "GraphQL", searchOperator: AND) { title url searchScore } } query { pages(inMenu: true, order: "title") { title url showInMenus } } ``` -------------------------------- ### GraphQL Query for Snippet Data Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/model-types.rst An example GraphQL query to fetch data from a page that includes a snippet field. This query demonstrates how to select specific fields from the referenced snippet. ```graphql { page(slug: "some-blog-page") { advert { url text } } } ``` -------------------------------- ### Querying Pages - Basic Queries Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Provides guidance on querying Wagtail pages using various identifiers such as ID, slug, or URL path. ```APIDOC ## Querying Pages - Basic Queries This section describes how to perform basic queries to retrieve Wagtail pages from the GraphQL API. You can query pages by their unique ID, slug, or URL path. ### Query Single Page by ID **Query:** ```graphql query { page(id: 3) { title slug url pageType contentType seoTitle searchDescription } } ``` **Success Response (200):** ```json { "data": { "page": { "title": "About Us", "slug": "about-us", "url": "/about-us/", "pageType": "testapp.ContentPage", "contentType": "contentpage", "seoTitle": "About Us - Company Name", "searchDescription": "Learn more about our company" } } } ``` ### Query Page by Slug **Query:** ```graphql query { page(slug: "contact") { title lastPublishedAt firstPublishedAt } } ``` ### Query Page by URL Path **Query:** ```graphql query { page(urlPath: "/blog/my-post/") { title url } } ``` ### Query Page with Site Filtering **Query:** ```graphql query { page(slug: "homepage", inSite: true) { title url } } ``` ``` -------------------------------- ### GraphQL Collections and Lists Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Explains how to handle collections of related objects, including the use of pagination for managing large datasets. ```APIDOC ## GraphQL Collections and Lists This section covers how to query collections of related objects and lists within your GraphQL schema. It highlights the use of `GraphQLCollection` for managing these relationships, including optional pagination. ### Example: Querying a Team Page with Team Members This example shows how to fetch a `TeamPage` and its associated `teamMembers`, which is a collection of `TeamMember` objects. **Query:** ```graphql query { teamPage(slug: "our-team") { description teamMembers { name role bio } } } ``` **Success Response (200):** ```json { "data": { "teamPage": { "description": "Meet our amazing team", "teamMembers": [ { "name": "Sarah Lee", "role": "CEO", "bio": "Visionary leader with 15 years of experience" }, { "name": "Mike Chen", "role": "CTO", "bio": "Technology expert passionate about innovation" } ] } } } ``` ``` -------------------------------- ### Headless Preview with Tokens (Python) Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Enables headless preview functionality for Wagtail pages by integrating with wagtail-headless-preview. This allows fetching draft or unpublished content using a secure token. It defines a Page model with GraphQL fields and demonstrates a sample GraphQL query for previewing content. ```python from wagtail.models import Page from wagtail_headless_preview.models import HeadlessPreviewMixin from grapple.models import GraphQLString, GraphQLStreamfield import models class BlogPage(HeadlessPreviewMixin, Page): author = models.CharField(max_length=255) body = StreamField([...]) graphql_fields = [ GraphQLString("author"), GraphQLStreamfield("body"), ] # Query with preview token (from wagtail-headless-preview) """ query { page(token: "id=42:page_type=blog.blogpage:timestamp=1234567890:signature=abc123") { ... on BlogPage { title author body { blockType ... on CharBlock { value } } } } } # Returns unpublished/draft content when valid token provided Response: { "data": { "page": { "title": "Draft Article (Preview)", "author": "Editor", "body": [ { "blockType": "CharBlock", "value": "This is draft content" } ] } } } """ ``` -------------------------------- ### Python: Wagtail BlogPage Model Configuration for Grapple Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/examples.rst Defines a Wagtail BlogPage model with fields and configures 'graphql_fields' for Grapple to generate GraphQL types. This allows the model's data to be queried via GraphQL. ```python from django.db import models from grapple.models import GraphQLRichText, GraphQLStreamfield, GraphQLString from wagtail import blocks from wagtail.models import Page from wagtail.images.blocks import ImageBlock from wagtail.fields import RichTextField, StreamField from wagtail.admin.edit_handlers import FieldPanel class BlogPage(Page): author = models.CharField(max_length=255) date = models.DateField("Post date") summary = RichTextField() body = StreamField( [ ("heading", blocks.CharBlock(classname="full title")), ("paragraph", blocks.RichTextBlock()), ("image", ImageBlock()), ] ) content_panels = Page.content_panels + [ FieldPanel("author"), FieldPanel("date"), FieldPanel("summary"), FieldPanel("body"), ] # Note these fields below: graphql_fields = [ GraphQLString("heading"), GraphQLString("date"), GraphQLString("author"), GraphQLRichText("summary"), GraphQLStreamfield("body"), ] ``` -------------------------------- ### GraphQL Streamfield for Nested Blocks in Python Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/model-types.rst Demonstrates how to use GraphQLStreamfield to represent nested StreamField blocks. It includes examples for handling lists of custom blocks (ButtonBlock) and direct StructBlocks, as well as integrating with paginated query fields. ```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")] ``` -------------------------------- ### Headless Preview with Tokens Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Enables preview functionality for headless CMS implementations by allowing queries with preview tokens to access unpublished or draft content. ```APIDOC ## Headless Preview with Tokens ### Description Support preview functionality for headless CMS implementations. This endpoint allows you to preview unpublished or draft content using a valid preview token. ### Method GET (or POST depending on GraphQL client) ### Endpoint `/graphql` (or your GraphQL endpoint) ### Parameters #### Query Parameters - **token** (string) - Required - A unique token generated by `wagtail-headless-preview` to access draft content. Format: `id=PAGE_ID:page_type=PAGE_TYPE:timestamp=TIMESTAMP:signature=SIGNATURE` ### Request Example ```graphql query { page(token: "id=42:page_type=blog.blogpage:timestamp=1234567890:signature=abc123") { ... on BlogPage { title author body { blockType ... on CharBlock { value } } } } } ``` ### Response #### Success Response (200) - **data** (object) - Contains the queried page data. - **page** (object) - The requested page object. - **title** (string) - The title of the page. - **author** (string) - The author of the page. - **body** (array) - The content of the page body, potentially containing various block types. #### Response Example ```json { "data": { "page": { "title": "Draft Article (Preview)", "author": "Editor", "body": [ { "blockType": "CharBlock", "value": "This is draft content" } ] } } } ``` ``` -------------------------------- ### GraphQL Boolean Field Definition in Python Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/model-types.rst Illustrates the definition of a GraphQLBoolean field, including its name, required status, and optional arguments like description, deprecation reason, and source. The example demonstrates its use in a StreamField with a custom method. ```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 ``` -------------------------------- ### Query Images and Documents Source: https://context7.com/torchbox/wagtail-grapple/llms.txt Details on how to query Wagtail Image and Document models, retrieving associated metadata like URLs, dimensions, and file information. ```APIDOC ## GraphQL Query for Images and Documents ### Description This endpoint allows you to query Wagtail's `ImageField` and `DocumentField`. It provides access to metadata for images (like `src`, `width`, `height`, `alt`) and documents (like `url`, `fileSize`, `fileHash`). ### Method POST ### Endpoint /graphql ### Parameters #### Query Parameters None #### Request Body - **query** (string) - Required - The GraphQL query string. ### Request Example ```json { "query": "\nquery {\n page(slug: \"media-page\") {\n ... on MediaPage {\n title\n featuredImage {\n src\n url\n width\n height\n aspectRatio\n sizes\n alt\n }\n pdfDocument {\n url\n file\n fileSize\n fileHash\n createdAt\n }\n }\n }\n}\n" } ``` ### Response #### Success Response (200) - **data** (object) - The result of the GraphQL query. - **page** (object) - The queried page object. - **title** (string) - The title of the page. - **featuredImage** (object) - Metadata for the featured image. - **src** (string) - The source URL of the image. - **url** (string) - The accessible URL of the image. - **width** (integer) - The width of the image in pixels. - **height** (integer) - The height of the image in pixels. - **aspectRatio** (float) - The aspect ratio of the image. - **sizes** (string) - HTML 'sizes' attribute value for responsive images. - **alt** (string) - The alt text for the image. - **pdfDocument** (object) - Metadata for the PDF document. - **url** (string) - The accessible URL of the document. - **file** (string) - The file path relative to storage. - **fileSize** (integer) - The size of the file in bytes. - **fileHash** (string) - A hash of the file content. - **createdAt** (string) - The creation timestamp of the document. #### Response Example ```json { "data": { "page": { "title": "Media Gallery", "featuredImage": { "src": "/media/images/hero.original.jpg", "url": "/media/images/hero.jpg", "width": 1920, "height": 1080, "aspectRatio": 1.777, "sizes": "(max-width: 1920px) 100vw, 1920px", "alt": "Hero image" }, "pdfDocument": { "url": "/media/documents/whitepaper.pdf", "file": "documents/whitepaper.pdf", "fileSize": 2048576, "fileHash": "abc123def456", "createdAt": "2025-01-01T12:00:00Z" } } } } ``` ``` -------------------------------- ### Configure Wagtail Model for Grapple GraphQL Source: https://github.com/torchbox/wagtail-grapple/wiki/03:-Basic-Demo This Python code snippet demonstrates how to configure a Wagtail model, `BlogPage`, to be exposed via GraphQL using the `wagtail-grapple` library. It defines model fields and then specifies which of these fields should be made available in the GraphQL schema using `graphql_fields`. ```python from grapple.models import ( GraphQLString, GraphQLStreamfield, ) from wagtail.core.fields import StreamField from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel from wagtail.core.models import Page from wagtail.images.blocks import ImageChooserBlock from wagtail.core import blocks class BlogPage(Page): author = models.CharField(max_length=255) date = models.DateField("Post date") body = StreamField( [ ("heading", blocks.CharBlock(classname="full title")), ("paraagraph", blocks.RichTextBlock()), ("image", ImageChooserBlock()), ] ) content_panels = Page.content_panels + [ FieldPanel("author"), FieldPanel("date"), StreamFieldPanel("body"), ] # Note these fields below: graphql_fields = [ GraphQLString("heading"), GraphQLString("date"), GraphQLString("author"), GraphQLStreamfield("body"), ] ``` -------------------------------- ### Grapple Settings Configuration Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/decorators.rst Configure default and maximum page sizes for paginated queries using the GRAPPLE setting in settings.py. ```APIDOC ## Grapple Settings Configuration ### Description Customize the default number of items returned per page (`per_page`) and the maximum allowed value for `per_page` in paginated GraphQL queries. ### Method N/A (Configuration) ### Endpoint N/A (Configuration) ### Parameters #### Query Parameters N/A #### Request Body N/A ### Request Example ```python # settings.py GRAPPLE = { # ... "PAGE_SIZE": 10, # Default items per page "MAX_PAGE_SIZE": 100, # Maximum allowed items per page } ``` ### Response N/A (Configuration) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Accessing Grapple Settings Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/getting-started/settings.rst Demonstrates how to access Wagtail Grapple configuration settings programmatically within your Django application. ```APIDOC ## Accessing Grapple Settings ### Description This section explains how to retrieve Wagtail Grapple settings in your Python code using the `grapple_settings` object. This object provides access to both user-defined settings and default values. ### Method Import and access the `grapple_settings` object. ### Endpoint Not applicable (Python code) ### Parameters N/A ### Request Example ```python from grapple.settings import grapple_settings # Accessing a specific setting print(grapple_settings.APPS) print(grapple_settings.AUTO_CAMELCASE) ``` ### Response N/A (Code execution output) #### Success Response (200) N/A #### Response Example ``` ['home'] True ``` ``` -------------------------------- ### GraphQL Query for Configured Wagtail Model Source: https://github.com/torchbox/wagtail-grapple/wiki/03:-Basic-Demo This GraphQL query demonstrates how to retrieve data from a Wagtail `BlogPage` model that has been configured with `wagtail-grapple`. It shows how to access basic string fields, the `StreamField` content, and nested blocks within the `StreamField`, such as images. ```graphql { pages { ...on BlogPage { heading date author body { rawValue ...on ImageChooserBlock { image { src } } } } } } ``` -------------------------------- ### Configure Wagtail Apps for Grapple Source: https://github.com/torchbox/wagtail-grapple/blob/main/README.md This Python code snippet demonstrates how to configure your Wagtail settings to enable Grapple and specify the Django apps that Grapple should scan for models. Ensure 'grapple' and 'graphene_django' are in INSTALLED_APPS. ```python INSTALLED_APPS = [ # ... "grapple", "graphene_django", # ... ] # Grapple config: GRAPHENE = {"SCHEMA": "grapple.schema.schema"} GRAPPLE = { "APPS": ["home"], } ``` -------------------------------- ### GraphQL SettingObjectType and SiteObjectType Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Details how to query settings grouped under SettingObjectType and site information via SiteObjectType. This includes querying all sites, a specific site by ID or hostname, and related pages. ```APIDOC ## GraphQL SettingObjectType and SiteObjectType ### Description Provides methods for querying settings and site information. ### SettingObjectType Settings are grouped under the `SettingObjectType` union. You can query specific settings by appending a `...on` clause for the setting type. #### Querying all settings ```graphql query { settings { ...on SocialMediaSettings { facebook instagram youtube } } } ``` #### Querying a specific setting by name ```graphql query { setting(name: "SocialMediaSettings") { ...on SocialMediaSettings { facebook instagram youtube } } } ``` ### SiteObjectType Accessible through the `sites` or `site` field on the root query type. #### Fields - **id** (ID) - Unique identifier for the site. - **port** (Int) - The port number for the site. - **siteName** (String) - The name of the site. - **hostname** (String) - The hostname of the site. - **isDefaultSite** (Boolean) - Indicates if this is the default site. - **rootPage** (PageInterface) - The root page of the site. - **page** (PageInterface) - Retrieves a specific page based on provided arguments (id, slug, urlPath, contentType, token). - **pages** ([PageInterface]) - Retrieves a list of pages with optional filtering and pagination. #### Querying all sites ```graphql query { sites { port hostname } } ``` #### Querying a specific site by hostname ```graphql query { site(hostname: "my.domain") { pages { title } } } ``` #### Arguments for `site` field: - **id** (ID) - The ID of the site (either `id` or `hostname` must be provided). - **hostname** (String) - The hostname of the site (either `id` or `hostname` must be provided). ``` -------------------------------- ### Image srcSet Fields Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Details the fields for generating responsive image source sets using the `srcSet` field on ImageObjectType, useful for different screen sizes and formats. ```graphql query { images { srcSet(sizes: [300, 600, 900]) } } ``` -------------------------------- ### Query Site Page by Path Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Shows how to retrieve a specific page within a site using the `page` field and the `urlPath` argument. ```graphql query { site(hostname: "my.domain.com") { page(urlPath: "/about-us/") { title } } } ``` -------------------------------- ### Query Settings by Type Source: https://github.com/torchbox/wagtail-grapple/blob/main/docs/general-usage/graphql-types.rst Demonstrates how to query grouped settings (like SocialMediaSettings) using the SettingObjectType union and a fragment. Requires the setting model to have a `graphql_fields` list. ```graphql query { settings { ...on SocialMediaSettings { facebook instagram youtube } } } ```