A stupid simple GraphQL setup for Django
Project description
django-simple-graphql
A stupid simple GraphQL setup for Django
This project is still a WIP and will receive breaking changes
TODO
- Support mutations
- Support subscriptions
- An easy default for authentication
- Account for reverse-relations automatically
- Handle django-graphene issue with relations ponting to non-pk fields and ID encoding
- Configurability
- Custom set of node interfaces (currently relay.Node)
- Custom relation connection handler (currently DjangoFilterConnectionField)
- Custom node/query/mutation/subscription builder functions
- Custom schema member naming
- Custom search
- Enable/disable search globally
- Enable/disable ordering globally
- Global default ordering options
- Injection of GraphQL ID property to models, configurable name and/or disable
- Examples
- More lax version pinning (Min python 3.5 or higher)
- Test suite against multiple version configurations
- Proper readme
- Better type definitions
- GraphQL schema docstring generation
- Validation checks when building the schema to prevent blatantly incorrect config
- For example, a field in search fields that doesn't exist or isn't supported
- Perhaps a way to auto-render the schema for github diffs?
- A way to easily include extra queries for models (e.g. with different filters)
- Require either field exclusions or inclusions to be explicitly defined
- Build a namespace package instead of a normal one (use "simple_graphql" as namespace root)
- Don't be as tightly coupled with graphene
- e.g. support to https://github.com/strawberry-graphql/strawberry would be nice
- Automatic CRUD operations
- Support more complex ordering options (as well as explicit naming of ordering)
- Run tests for code included in documentation
- Support for permissions
- Query cost analysis / rate limiting
- Consider supporting an alternative approach where registration decorator could be applied to a GraphQL config object instead of the model class
- Allow the register decorator be used with or without function call. Possibly also allow it's use as a non-decorator registering function.
- Add support for using the schema builder if there's need to combine with an existing graphene schema declaration.
Features (already supported)
TODO: Improve the documentation
- Enable GraphQL queries for Django models with a decorator
- By default, includes a
getModelName
andlistModelName
queries - Configure by adding a
GraphQL
meta class to the model class - Alternatively supply a configuration class to the decorator
- By default, includes a
- Supported configuration options
filters
: Adjango-filter
compatible set of filters supported on the model's QuerySet. List or a Dictionary.exclude_fields
: A list of field names to exclude from the schemasearch_fields
: A list of fields to perform search onordering_fields
: A list of fields that can be used to order resultsdefault_ordering
: What ordering to use if none was specified
- Adds a
graphql_node_name
field to model classes - Adds a
graphql_id
property to models, which can be used to retrieve the Global ID of a model instance.
Usage
Setup
Steps 1-3 are setup for graphene-django
.
See https://docs.graphene-python.org/projects/django/en/latest/installation/ for
more details.
If you are already using graphene-django
, you can skip to step 4.
- Add
graphene-django
to yourINSTALLED_APPS
:INSTALLED_APPS = [ # ... "django.contrib.staticfiles", # Required for GraphiQL "graphene_django", ]
- Add a GraphQL endpoint to the URL config:
from django.urls import path from django.views.decorators.csrf import csrf_exempt from graphene_django.views import GraphQLView urlpatterns = [ # ... path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))), ]
- Create a schema file (e.g.
schema.py
) and configure it to Graphene:# settings.py GRAPHENE = { "SCHEMA": "myapp.shcema.schema", }
- Declare the schema in your schema file
# schema.py from simple_graphql.django import Schema schema = Schema()
Default queries
By default, all model classes registered to the schema will get a query for fetching a single object by ID as well as a list query.
For the sake of an example, let's say we have the following model declaration:
from django.db import models
from myapp.schema import schema
@schema.graphql_model()
class Person(models.Model):
first_name = models.TextField()
last_name = models.TextField()
The graphql_model
decorator will add the model to our GraphQL schema builder,
which will build it into the following schema (relay schema omitted):
type Person implements Node {
id: ID!
lastName: String!
firstName: String!
}
type Query {
getPerson(id: ID!): Person
listPerson(after: String, before: String, first: Int, last: Int, offset: Int): PersonConnection
}
For a more complete example of the generated schema, see example/schema.graphql
Search
TODO
Examples
Registering models
There's two ways models can be added to the schema
With a class decorator
from django.db import models
from myapp.schema import schema
@schema.graphql_model()
class Person(models.Model):
first_name = models.TextField()
last_name = models.TextField()
With a function call
from django.contrib.auth import get_user_model
from myapp.schema import schema
User = get_user_model()
schema.register_model(User)
Configuring models
Model specific schemas can be configured either with a metaclass or passed in as a parameter. A base configuration also is present regardless of custom declarations.
If multiple configurations are present, they will be merged in the following precedence:
- Configuration supplied via parameters
- Metaclass based configuration
- Default configuration
Where lower number means higher priority.
Metaclass configuration
from django.db import models
from myapp.schema import schema
@schema.graphql_model()
class Person(models.Model):
first_name = models.TextField()
last_name = models.TextField()
credit_card_number = models.TextField()
parent = models.ForeignKey("self", on_delete=models.SET_NULL)
class GraphQL:
exclude_fields = ["credit_card_number"]
ordering_fields = ["first_name", "last_name"]
default_ordering = ["first_name"]
search_fields = ["first_name", "last_name"]
filters = ["parent"]
@staticmethod
def get_queryset(queryset: QuerySet["Person"], info: Any):
if info.context.user.is_superuser:
return queryset
return queryset.none()
Parameter configuration (with a class)
from django.db import models
from myapp.schema import schema
class PersonGraphQLConfig:
exclude_fields = ["credit_card_number"]
ordering_fields = ["first_name", "last_name"]
default_ordering = ["first_name"]
search_fields = ["first_name", "last_name"]
filters = ["parent"]
@schema.graphql_model(PersonGraphQLConfig)
class Person(models.Model):
first_name = models.TextField()
last_name = models.TextField()
credit_card_number = models.TextField()
parent = models.ForeignKey("self", on_delete=models.SET_NULL)
Parameter configuration (with a config object)
from django.db import models
from simple_graphql.django import ModelSchemaConfig
from myapp.schema import schema
@schema.graphql_model(ModelSchemaConfig(
exclude_fields=["credit_card_number"],
ordering_fields=["first_name", "last_name"],
default_ordering=["first_name"],
search_fields=["first_name", "last_name"],
filters=["parent"],
))
class Person(models.Model):
first_name = models.TextField()
last_name = models.TextField()
credit_card_number = models.TextField()
parent = models.ForeignKey("self", on_delete=models.SET_NULL)
Parameter configuration (function variant)
from django.contrib.auth import get_user_model
from simple_graphql.django import ModelSchemaConfig
from myapp.schema import schema
User = get_user_model()
# Could also use a class here just like with the decorator
schema.register_model(User, ModelSchemaConfig(
exclude_fields=["password"],
))
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
File details
Details for the file django-simple-graphql-0.5.0.tar.gz
.
File metadata
- Download URL: django-simple-graphql-0.5.0.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.8 CPython/3.8.6 Windows/10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce6d1db6a42878809289435811e804419fbdc787d7f62451c3fd6d3e13ca9ddc |
|
MD5 | 36938afda9c894e4a9d48716d5d5ba33 |
|
BLAKE2b-256 | 1bb665b8180ddea4a499cac5eba5b47b4c848d3570b54626e1b0feb61136c79b |
File details
Details for the file django_simple_graphql-0.5.0-py3-none-any.whl
.
File metadata
- Download URL: django_simple_graphql-0.5.0-py3-none-any.whl
- Upload date:
- Size: 22.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.8 CPython/3.8.6 Windows/10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 634badd0aafecdbbaa03775c36f4ba09d9230e9960566d806a58ab47dcb7f281 |
|
MD5 | c107a4da774f2aa860a0fd0d26b036aa |
|
BLAKE2b-256 | e29ce1a3dc1f46e034bdc4a093a525ce87eeb66b9b2ed5cf13b105c3d78f32bf |