### 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.
- Innovation
- Quality
- Reliability
"
}
}
}
```
--------------------------------
### 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
}
}
}
```