Skip to content

Commit 4915cc8

Browse files
committed
feat: native federation integration
1 parent 4f6cf8e commit 4915cc8

File tree

12 files changed

+1869
-22
lines changed

12 files changed

+1869
-22
lines changed

RELEASE.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
release type: minor
3+
---
4+
5+
Add native federation support via `strawberry_django.federation` module.
6+
7+
New decorators that combine `strawberry_django` functionality with Apollo Federation:
8+
9+
- `strawberry_django.federation.type` - Federation-aware Django type with auto-generated `resolve_reference`
10+
- `strawberry_django.federation.interface` - Federation-aware Django interface
11+
- `strawberry_django.federation.field` - Federation-aware Django field with directives like `@external`, `@requires`, `@provides`
12+
13+
Example usage:
14+
15+
```python
16+
import strawberry
17+
import strawberry_django
18+
from strawberry.federation import Schema
19+
20+
@strawberry_django.federation.type(models.Product, keys=["upc"])
21+
class Product:
22+
upc: strawberry.auto
23+
name: strawberry.auto
24+
price: strawberry.auto
25+
# resolve_reference is automatically generated!
26+
27+
schema = Schema(query=Query)
28+
```
29+
30+
The auto-generated `resolve_reference` methods support composite keys and multiple keys, and integrate with the query optimizer.

docs/integrations/federation.md

Lines changed: 137 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,36 @@ title: Federation
66

77
Strawberry Django works seamlessly with
88
[Strawberry's Federation support](https://strawberry.rocks/docs/guides/federation).
9-
Since federation is handled at the Strawberry level, you can use all federation
10-
features directly with your Django types.
9+
You can use either Strawberry's federation decorators directly or the Django-specific
10+
`strawberry_django.federation` module which provides auto-generated `resolve_reference`
11+
methods.
1112

12-
## Basic Usage
13+
## Using `strawberry_django.federation` (Recommended)
1314

14-
Use Strawberry's federation decorators alongside `strawberry_django`:
15+
The `strawberry_django.federation` module provides Django-aware federation decorators
16+
that automatically generate `resolve_reference` methods for your entity types:
1517

1618
```python
1719
import strawberry
1820
import strawberry_django
19-
from strawberry.federation.schema_directives import Key
21+
from strawberry.federation import Schema as FederationSchema
2022

2123
from . import models
2224

2325

24-
@strawberry_django.type(models.Product, directives=[Key(fields="upc")])
26+
@strawberry_django.federation.type(models.Product, keys=["upc"])
2527
class Product:
2628
upc: strawberry.auto
2729
name: strawberry.auto
2830
price: strawberry.auto
31+
# resolve_reference is automatically generated!
2932

3033

31-
@strawberry_django.type(models.Review, directives=[Key(fields="id")])
34+
@strawberry_django.federation.type(models.Review, keys=["id"])
3235
class Review:
3336
id: strawberry.auto
3437
body: strawberry.auto
3538
product: Product
36-
```
37-
38-
## Creating a Federated Schema
39-
40-
Use `strawberry.federation.Schema` instead of the regular `strawberry.Schema`:
41-
42-
```python
43-
import strawberry
44-
from strawberry.federation import Schema
4539

4640

4741
@strawberry.type
@@ -51,14 +45,117 @@ class Query:
5145
return models.Product.objects.all()
5246

5347

54-
schema = Schema(query=Query, enable_federation_2=True)
48+
schema = FederationSchema(query=Query)
49+
```
50+
51+
### Federation Parameters
52+
53+
The `@strawberry_django.federation.type` decorator accepts all standard
54+
`@strawberry_django.type` parameters plus federation-specific ones:
55+
56+
| Parameter | Type | Description |
57+
| ----------------- | ----------------- | ------------------------------------------------------------------------- |
58+
| `keys` | `list[str]` | Key fields for entity resolution (e.g., `["id"]` or `["sku", "package"]`) |
59+
| `extend` | `bool` | Whether this type extends a type from another subgraph |
60+
| `shareable` | `bool` | Whether this type can be resolved by multiple subgraphs |
61+
| `inaccessible` | `bool` | Whether this type is hidden from the public API |
62+
| `authenticated` | `bool` | Whether this type requires authentication |
63+
| `policy` | `list[list[str]]` | Access policy for this type |
64+
| `requires_scopes` | `list[list[str]]` | Required OAuth scopes for this type |
65+
| `tags` | `list[str]` | Metadata tags for this type |
66+
67+
### Multiple Keys
68+
69+
You can define multiple key fields:
70+
71+
```python
72+
@strawberry_django.federation.type(models.Product, keys=["id", "upc"])
73+
class Product:
74+
id: strawberry.auto
75+
upc: strawberry.auto
76+
name: strawberry.auto
77+
```
78+
79+
### Composite Keys
80+
81+
For composite keys (multiple fields that together form a key), use a space-separated
82+
string:
83+
84+
```python
85+
@strawberry_django.federation.type(models.ProductVariant, keys=["sku package"])
86+
class ProductVariant:
87+
sku: strawberry.auto
88+
package: strawberry.auto
89+
price: strawberry.auto
90+
```
91+
92+
### Custom `resolve_reference`
93+
94+
If you need custom logic, you can still define your own `resolve_reference`:
95+
96+
```python
97+
@strawberry_django.federation.type(models.Product, keys=["upc"])
98+
class Product:
99+
upc: strawberry.auto
100+
name: strawberry.auto
101+
102+
@classmethod
103+
def resolve_reference(cls, upc: str, info: Info) -> "Product":
104+
# Custom implementation with select_related
105+
return models.Product.objects.select_related("category").get(upc=upc)
106+
```
107+
108+
### Federation Fields
109+
110+
Use `strawberry_django.federation.field` for federation-specific field directives:
111+
112+
```python
113+
@strawberry_django.federation.type(models.Product, keys=["id"])
114+
class Product:
115+
id: strawberry.auto
116+
name: strawberry.auto = strawberry_django.federation.field(external=True)
117+
price: strawberry.auto = strawberry_django.federation.field(shareable=True)
118+
display_name: str = strawberry_django.federation.field(requires=["name"])
119+
```
120+
121+
Field parameters:
122+
123+
| Parameter | Type | Description |
124+
| ----------------- | ----------------- | ------------------------------------------------ |
125+
| `authenticated` | `bool` | Whether this field requires authentication |
126+
| `external` | `bool` | Field is defined in another subgraph |
127+
| `requires` | `list[str]` | Fields required from other subgraphs |
128+
| `provides` | `list[str]` | Fields this resolver provides to other subgraphs |
129+
| `override` | `str` | Override field from another subgraph |
130+
| `policy` | `list[list[str]]` | Access policy for this field |
131+
| `requires_scopes` | `list[list[str]]` | Required OAuth scopes for this field |
132+
| `shareable` | `bool` | Field can be resolved by multiple subgraphs |
133+
| `tags` | `list[str]` | Metadata tags for this field |
134+
| `inaccessible` | `bool` | Field is hidden from the public API |
135+
136+
### Interfaces
137+
138+
Federation interfaces are also supported:
139+
140+
```python
141+
@strawberry_django.federation.interface(models.Product, keys=["id"])
142+
class ProductInterface:
143+
id: strawberry.auto
144+
name: strawberry.auto
55145
```
56146

57-
## Reference Resolvers
147+
## Using Strawberry's Federation Directly
58148

59-
When other services need to resolve your Django entities, define `resolve_reference`:
149+
You can also use Strawberry's federation decorators alongside `strawberry_django`:
60150

61151
```python
152+
import strawberry
153+
import strawberry_django
154+
from strawberry.federation.schema_directives import Key
155+
156+
from . import models
157+
158+
62159
@strawberry_django.type(models.Product, directives=[Key(fields="upc")])
63160
class Product:
64161
upc: strawberry.auto
@@ -70,6 +167,24 @@ class Product:
70167
return models.Product.objects.get(upc=upc)
71168
```
72169

170+
## Creating a Federated Schema
171+
172+
Use `strawberry.federation.Schema` instead of the regular `strawberry.Schema`:
173+
174+
```python
175+
from strawberry.federation import Schema
176+
177+
178+
@strawberry.type
179+
class Query:
180+
@strawberry_django.field
181+
def products(self) -> list[Product]:
182+
return models.Product.objects.all()
183+
184+
185+
schema = Schema(query=Query)
186+
```
187+
73188
## Django-Specific Considerations
74189

75190
### Query Optimizer
@@ -82,11 +197,13 @@ from strawberry_django.optimizer import DjangoOptimizerExtension
82197

83198
schema = Schema(
84199
query=Query,
85-
enable_federation_2=True,
86200
extensions=[DjangoOptimizerExtension],
87201
)
88202
```
89203

204+
The auto-generated `resolve_reference` methods integrate with the query optimizer
205+
when using `strawberry_django.federation`.
206+
90207
### Authentication
91208

92209
When using federation with Django authentication, ensure your gateway forwards

strawberry_django/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import warnings
22
from typing import TYPE_CHECKING, Any
33

4-
from . import auth, filters, mutations, ordering, pagination, relay
4+
from . import auth, federation, filters, mutations, ordering, pagination, relay
55
from .fields.field import connection, field, node, offset_paginated
66
from .fields.filter_order import filter_field, order_field
77
from .fields.filter_types import (
@@ -56,6 +56,7 @@
5656
"auth",
5757
"connection",
5858
"django_resolver",
59+
"federation",
5960
"field",
6061
"filter_field",
6162
"filter_type",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""Federation support for strawberry-django.
2+
3+
This module provides Django-aware federation decorators that combine
4+
`strawberry_django` functionality with Apollo Federation support.
5+
6+
- `type` - Federation-aware Django type decorator
7+
- `interface` - Federation-aware Django interface decorator
8+
- `field` - Federation-aware Django field decorator
9+
10+
The type and interface decorators automatically generate `resolve_reference`
11+
methods for entity types (those with `@key` directives).
12+
13+
See docs/integrations/federation.md for full usage examples.
14+
"""
15+
16+
from .field import field
17+
from .resolve import generate_resolve_reference, resolve_model_reference
18+
from .type import interface
19+
from .type import type as type # noqa: A004
20+
21+
__all__ = [
22+
"field",
23+
"generate_resolve_reference",
24+
"interface",
25+
"resolve_model_reference",
26+
"type",
27+
]

0 commit comments

Comments
 (0)