A set of tools for using dataloaders with Django and Strawberry GraphQL.
Project description
Dataloaders for Django and Strawberry
A set of tools for using dataloaders with Django and Strawberry without unnecessary boilerplate.
Installation
TODO
Usage & examples
This package provides 3 levels of generating dataloaders, each offering higher level of abstraction than the previous one.
Models definition
Definition of models used in the examples.
from django.db import models
class Fruit(models.Model):
plant = models.OneToOneField("FruitPlant", ...)
color = models.ForeignKey("Color", ...)
varieties = models.ManyToManyField("FruitVariety", ..., related_name="fruits")
class FruitEater(models.Model):
favourite_fruit = models.ForeignKey("Fruit", ..., related_name="eaters")
Level 1: Simple dataloader
On the first level, we're defining and using different dataloader for each relationship.
One-to-one and Many-to-one relationship
- Define the dataloaders
from strawberry_django_dataloaders import dataloaders
class ColorPKDataLoader(dataloaders.BasicPKDataLoader):
model = models.Color
class FruitPlantPKDataLoader(dataloaders.BasicPKDataLoader):
model = models.FruitPlant
- Use them when defining the Strawberry type
@strawberry_django.type(models.Fruit)
class FruitType:
id: strawberry.auto
### ↓ HERE ↓ ###
@strawberry.field
async def color(self: "models.Fruit", info: "Info") -> ColorType | None:
return await dataloaders.ColorPKDataLoader(context=info.context).load(self.color_id)
@strawberry.field
async def plant(self: "models.Fruit", info: "Info") -> FruitPlantType | None:
return await dataloaders.FruitPlantPKDataLoader(context=info.context).load(self.plant_id)
One-to-many relationship
- Define the dataloader
from strawberry_django_dataloaders import dataloaders
class FruitEatersReverseFKDataLoader(dataloaders.BasicReverseFKDataLoader):
model = models.FruitEater
reverse_path = "favourite_fruit_id" # <-- is the "reverse" FK field from FruitEater to Fruit model
- Use it when defining the Strawberry type
@strawberry_django.type(models.Fruit)
class FruitType:
id: strawberry.auto
### ↓ HERE ↓ ###
@strawberry.field
async def eaters(self: "models.Fruit", info: "Info") -> list[FruitEaterType]:
return await dataloaders.FruitEatersReverseFKDataLoader(context=info.context).load(self.pk)
Level 2: Dataloader factories
When using the dataloader factories, we no longer need to define a dataloader for each relation.
from strawberry_django_dataloaders import factories
@strawberry_django.type(models.Fruit)
class FruitTypeDataLoaderFactories:
id: strawberry.auto
### ↓ ONE-TO-ONE AND MANY-TO-ONE DATALOADERS ↓ ###
@strawberry.field
async def color(self: "models.Fruit", info: "Info") -> ColorType | None:
loader = factories.PKDataLoaderFactory.get_loader_class("tests.Color")
return await loader(context=info.context).load(self.color_id)
@strawberry.field
async def plant(self: "models.Fruit", info: "Info") -> FruitPlantType | None:
loader = factories.PKDataLoaderFactory.get_loader_class("tests.FruitPlant")
return await loader(context=info.context).load(self.plant_id)
### ↓ ONE-TO-MANY DATALOADER ↓ ###
@strawberry.field
async def eaters(self: "models.Fruit", info: "Info") -> list[FruitEaterType]:
loader = factories.ReverseFKDataLoaderFactory.get_loader_class(
"tests.FruitEater",
reverse_path="favourite_fruit_id",
)
return await loader(context=info.context).load(self.color_id)
Level 3: Auto dataloader field
A field used in a similar fashion as native Django strawberry field, but it has auto-defined correct dataloader handler based on the field relationship.
from strawberry_django_dataloaders import fields
@strawberry_django.type(models.Fruit)
class FruitTypeAutoDataLoaderFields:
id: strawberry.auto
color: ColorType = fields.auto_dataloader_field()
plant: FruitPlantType = fields.auto_dataloader_field()
varieties: list[FruitVarietyType] = fields.auto_dataloader_field()
eaters: list[FruitEaterType] = fields.auto_dataloader_field()
Contributing
Pull requests for any improvements are welcome.
Poetry is used to manage dependencies. To get started follow these steps:
git clone https://github.com/VojtechPetru/strawberry-django-dataloaders
cd strawberry-django-dataloaders
poetry install
poetry run pytest
Pre commit
We have a configuration for pre-commit, to add the hook run the following command:
pre-commit install
Links
- Inspired and builds on top of a great article at: https://alexcleduc.com/posts/graphql-dataloader-composition/
- Repository: https://github.com/VojtechPetru/strawberry-django-dataloaders
- Issue tracker: https://github.com/VojtechPetru/strawberry-django-dataloaders/issues. In case of sensitive bugs (e.g. security vulnerabilities) please contact me at petru.vojtech@gmail.com directly.
Known issues/shortcomings
Many-to-many
relation is currently not supported.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for strawberry-django-dataloaders-0.1.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | fa38311ef6004685f3966fcff7c02f6300e97dedcb6beeecc726b82dc31c533e |
|
MD5 | a3040b43931148c3a3429161bfa339ea |
|
BLAKE2b-256 | 076445bd5e6bb19bf82e0ea006c0afe2ee252134292dc507655325022c62156b |
Hashes for strawberry_django_dataloaders-0.1.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bc4a693749b81535f5dc33453b56813fb6bdfcb5dc5260ee919806a1fdc959bd |
|
MD5 | a606492d8a7fb9f8537bea252442d879 |
|
BLAKE2b-256 | 6dab6b69d81eae5e230bca830b4235156a8b75f68be54386e53c3a754381ee37 |