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
|
---
title: Defining Fields
---
# Defining Fields
> [!TIP]
> It is highly recommended to enable the [Query Optimizer Extension](optimizer.md)
> for improved performance and avoid some common pitfalls (e.g. the `n+1` issue)
Fields can be defined manually or `auto` type can be used for automatic type resolution. All basic field types and relation fields are supported out of the box. If you use a library that defines a custom field you will need to define an equivalent type such as `str`, `float`, `bool`, `int` or `id`.
```python title="types.py"
import strawberry_django
from strawberry import auto
@strawberry_django.type(models.Fruit)
class Fruit:
id: auto
name: auto
# equivalent type, inferred by `strawberry`
@strawberry_django.type(models.Fruit)
class Fruit2:
id: strawberry.ID
name: str
```
> [!TIP]
> For choices using
> [Django's TextChoices/IntegerChoices](https://docs.djangoproject.com/en/4.2/ref/models/fields/#enumeration-types)
> it is recommented using the [django-choices-field](../integrations/choices-field.md) integration
> enum handling.
## Relationships
All one-to-one, one-to-many, many-to-one and many-to-many relationship types are supported, and the many-to-many relation is described using the `typing.List` annotation.
The default resolver of `strawberry_django.fields()` resolves the relationship based on given type information.
```python title="types.py"
@strawberry_django.type(models.Fruit)
class Fruit:
id: auto
name: auto
color: "Color"
@strawberry_django.type(models.Color)
class Color:
id: auto
name: auto
fruits: list[Fruit]
```
Note that all relations can naturally trigger the n+1 problem. To avoid that, you can either
enable the [Optimizer Extension](./optimizer.md) which will automatically
solve some general issues for you, or even use
[Data Loaders](https://strawberry.rocks/docs/guides/dataloaders) for more complex
situations.
## Field customization
All Django types are encoded using the `strawberry_django.field()` field type by default. Fields can be customized with various parameters.
```python title="types.py"
@strawberry_django.type(models.Color)
class Color:
another_name: auto = strawberry_django.field(field_name='name')
internal_name: auto = strawberry_django.field(
name='fruits',
field_name='fruit_set',
filters=FruitFilter,
order=FruitOrder,
pagination=True,
description="A list of fruits with this color"
)
```
## Defining types for auto fields
When using `strawberry.auto` to resolve a field's type, Strawberry Django uses a dict that maps
each django field field type to its proper type. e.g.:
```python
{
models.CharField: str,
models.IntegerField: int,
...,
}
```
If you are using a custom django field that is not part of the default library,
or you want to use a different type for a field, you can do that by overriding
its value in the map, like:
```python
from typing import NewType
from django.db import models
import strawberry
import strawberry_django
from strawberry_django.fields.types import field_type_map
Slug = strawberry.scalar(
NewType("Slug", str),
serialize=lambda v: v,
parse_value=lambda v: v,
)
@strawberry_django.type
class MyCustomFileType:
...
field_type_map.update({
models.SlugField: Slug,
models.FileField: MyCustomFileType,
})
```
## Including / excluding Django model fields by name
> [!WARNING]
> These new keywords should be used with caution, as they may inadvertently lead to exposure of unwanted data. Especially with `fields="__all__"` or `exclude`, sensitive model attributes may be included and made available in the schema without your awareness.
`strawberry_django.type` includes two optional keyword fields to help you populate fields from the Django model, `fields` and `exclude`.
Valid values for `fields` are:
- `__all__` to assign `strawberry.auto` as the field type for all model fields.
- `[<List of field names>]` to assign `strawberry.auto` as the field type for the enumerated fields. These can be combined with manual type annotations if needed.
```python title="All Fields"
@strawberry_django.type(models.Fruit, fields="__all__")
class FruitType:
pass
```
```python title="Enumerated Fields"
@strawberry_django.type(models.Fruit, fields=["name", "color"])
class FruitType:
pass
```
```python title="Overriden Fields"
@strawberry_django.type(models.Fruit, fields=["color"])
class FruitType:
name: str
```
Valid values for `exclude` are:
- `[<List of field names>]` to exclude from the fields list. All other Django model fields will included and have `strawberry.auto` as the field type. These can also be overriden if another field type should be assigned. An empty list is ignored.
```python title="Exclude Fields"
@strawberry_django.type(models.Fruit, exclude=["name"])
class FruitType:
pass
```
```python title="Overriden Exclude Fields"
@strawberry_django.type(models.Fruit, exclude=["name"])
class FruitType:
color: int
```
Note that `fields` has precedence over `exclude`, so if both are provided, then `exclude` is ignored.
## Overriding the field class (advanced)
If in your project, you want to change/add some of the standard `strawberry_django.field()` behaviour,
it is possible to use your own custom field class when decorating a `strawberry_django.type` with the `field_cls` argument, e.g.
```python title="types.py"
class CustomStrawberryDjangoField(StrawberryDjangoField):
"""Your custom behaviour goes here."""
@strawberry_django.type(User, field_cls=CustomStrawberryDjangoField)
class UserType:
# Each of these fields will be an instance of `CustomStrawberryDjangoField`.
id: int
name: auto
@strawberry.type
class UserQuery:
# You can directly create your custom field class on a plain strawberry type
user: UserType = CustomStrawberryDjangoField()
```
In this example, each of the fields of the `UserType` will be automatically created by `CustomStrawberryDjangoField`,
which may implement anything from custom pagination of relationships to altering the field permissions.
|