File: federation.md

package info (click to toggle)
strawberry-graphql-django 0.78.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,624 kB
  • sloc: python: 31,895; makefile: 24; sh: 21
file content (225 lines) | stat: -rw-r--r-- 7,589 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
---
title: Federation
---

# Federation

Strawberry Django works seamlessly with
[Strawberry's Federation support](https://strawberry.rocks/docs/guides/federation).
You can use either Strawberry's federation decorators directly or the Django-specific
`strawberry_django.federation` module which provides auto-generated `resolve_reference`
methods.

## Using `strawberry_django.federation` (Recommended)

The `strawberry_django.federation` module provides Django-aware federation decorators
that automatically generate `resolve_reference` methods for your entity types:

```python
import strawberry
import strawberry_django
from strawberry.federation import Schema as FederationSchema

from . import models


@strawberry_django.federation.type(models.Product, keys=["upc"])
class Product:
    upc: strawberry.auto
    name: strawberry.auto
    price: strawberry.auto
    # resolve_reference is automatically generated!


@strawberry_django.federation.type(models.Review, keys=["id"])
class Review:
    id: strawberry.auto
    body: strawberry.auto
    product: Product


@strawberry.type
class Query:
    @strawberry_django.field
    def products(self) -> list[Product]:
        return models.Product.objects.all()


schema = FederationSchema(query=Query)
```

### Federation Parameters

The `@strawberry_django.federation.type` decorator accepts all standard
`@strawberry_django.type` parameters plus federation-specific ones:

| Parameter         | Type               | Description                                                                          |
| ----------------- | ------------------ | ------------------------------------------------------------------------------------ |
| `keys`            | `list[str \| Key]` | Key fields for entity resolution (e.g., `["id"]` or `["sku package"]` for composite) |
| `extend`          | `bool`             | Whether this type extends a type from another subgraph                               |
| `shareable`       | `bool`             | Whether this type can be resolved by multiple subgraphs                              |
| `inaccessible`    | `bool`             | Whether this type is hidden from the public API                                      |
| `authenticated`   | `bool`             | Whether this type requires authentication                                            |
| `policy`          | `list[list[str]]`  | Access policy for this type                                                          |
| `requires_scopes` | `list[list[str]]`  | Required OAuth scopes for this type                                                  |
| `tags`            | `list[str]`        | Metadata tags for this type                                                          |

### Multiple Keys

You can define multiple key fields. Each string in the list creates a separate `@key`
directive — the entity can be resolved by **either** key independently:

```python
@strawberry_django.federation.type(models.Product, keys=["id", "upc"])
class Product:
    id: strawberry.auto
    upc: strawberry.auto
    name: strawberry.auto
```

### Composite Keys

For composite keys (multiple fields that together form a key), use a space-separated
string:

```python
@strawberry_django.federation.type(models.ProductVariant, keys=["sku package"])
class ProductVariant:
    sku: strawberry.auto
    package: strawberry.auto
    price: strawberry.auto
```

### Custom `resolve_reference`

If you need custom logic, you can still define your own `resolve_reference`:

```python
from strawberry.types.info import Info


@strawberry_django.federation.type(models.Product, keys=["upc"])
class Product:
    upc: strawberry.auto
    name: strawberry.auto

    @classmethod
    def resolve_reference(cls, upc: str, info: Info) -> "Product":
        # Custom implementation with select_related
        return models.Product.objects.select_related("category").get(upc=upc)
```

### Federation Fields

Use `strawberry_django.federation.field` for federation-specific field directives:

```python
@strawberry_django.federation.type(models.Product, keys=["id"])
class Product:
    id: strawberry.auto
    name: strawberry.auto = strawberry_django.federation.field(external=True)
    price: strawberry.auto = strawberry_django.federation.field(shareable=True)
    display_name: str = strawberry_django.federation.field(
        requires=["name"],
        resolver=lambda self: f"Product: {self.name}",
    )
```

Field parameters:

| Parameter         | Type              | Description                                      |
| ----------------- | ----------------- | ------------------------------------------------ |
| `authenticated`   | `bool`            | Whether this field requires authentication       |
| `external`        | `bool`            | Field is defined in another subgraph             |
| `requires`        | `list[str]`       | Fields required from other subgraphs             |
| `provides`        | `list[str]`       | Fields this resolver provides to other subgraphs |
| `override`        | `str`             | Override field from another subgraph             |
| `policy`          | `list[list[str]]` | Access policy for this field                     |
| `requires_scopes` | `list[list[str]]` | Required OAuth scopes for this field             |
| `shareable`       | `bool`            | Field can be resolved by multiple subgraphs      |
| `tags`            | `list[str]`       | Metadata tags for this field                     |
| `inaccessible`    | `bool`            | Field is hidden from the public API              |

### Interfaces

Federation interfaces are also supported:

```python
@strawberry_django.federation.interface(models.Product, keys=["id"])
class ProductInterface:
    id: strawberry.auto
    name: strawberry.auto
```

## Using Strawberry's Federation Directly

You can also use Strawberry's federation decorators alongside `strawberry_django`:

```python
import strawberry
import strawberry_django
from strawberry.federation.schema_directives import Key

from . import models


@strawberry_django.type(models.Product, directives=[Key(fields="upc")])
class Product:
    upc: strawberry.auto
    name: strawberry.auto
    price: strawberry.auto

    @classmethod
    def resolve_reference(cls, upc: str) -> "Product":
        return models.Product.objects.get(upc=upc)
```

## Creating a Federated Schema

Use `strawberry.federation.Schema` instead of the regular `strawberry.Schema`:

```python
from strawberry.federation import Schema


@strawberry.type
class Query:
    @strawberry_django.field
    def products(self) -> list[Product]:
        return models.Product.objects.all()


schema = Schema(query=Query)
```

## Django-Specific Considerations

### Query Optimizer

The [Query Optimizer](../guide/optimizer.md) works with federated schemas. Add the
extension as usual:

```python
from strawberry_django.optimizer import DjangoOptimizerExtension

schema = Schema(
    query=Query,
    extensions=[DjangoOptimizerExtension],
)
```

The auto-generated `resolve_reference` methods integrate with the query optimizer
when using `strawberry_django.federation`.

### Authentication

When using federation with Django authentication, ensure your gateway forwards
authentication headers. See [Authentication](../guide/authentication.md) for
configuring authentication in your Django service.

## Further Reading

For complete federation documentation, see:

- [Strawberry Federation Guide](https://strawberry.rocks/docs/guides/federation)
- [Federation Specification](https://www.apollographql.com/docs/federation/)