Tools to easily create permissioned CRUD endpoints in graphene.
Project description
graphene-django-plus
Tools to easily create permissioned CRUD endpoints in graphene-django.
Install
pip install graphene-django-plus
To make use of everything this lib has to offer, it is recommended to install both graphene-django-optimizer and django-guardian.
pip install graphene-django-optimizer django-guardian
What it does
- Provides some base types for Django Models to improve querying them with:
- Unauthenticated user handling
- Automatic optimization using graph-django-optimizer
- Permission handling for queries using the default django permission system
- Object permission handling for queries using django guardian
- Relay id conversion so querying can use the global id instead of the model's id
- Provides a set of complete and simple CRUD mutations with:
- Unauthenticated user handling
- Permission handling using the default django permission system
- Object permission handling using django guardian
- Automatic input generation based on the model (no need to write your own input type or use
django forms
anddrf serializers
) - Automatic model validation based on the model's validators
- Very simple to create some quick CRUD endpoints for your models
- Easy to extend and override functionalities
- File upload handling
What is included
Check the docs for a complete api documentation.
Models
graphene_django_plus.models.GuardedModel
: A django model that can be used either directly or as a mixin. It will provide a.has_perm
method and a.objects.for_user
that will be used byModelType
described bellow to check for object permissions. some utilities to check.
Types and Queries
-
graphene_django_plus.types.ModelType
: This enchancesgraphene_django_plus.DjangoModelType
by doing some automaticprefetch
optimization on setup and also checking for objects permissions on queries when it inherits fromGuardedModel
. -
graphene_django_plus.fields.CountableConnection
: This enchancesgraphene.relay.Connection
to provide atotal_count
attribute.
Here is an example describing how to use those:
import graphene
from graphene import relay
from graphene_django.fields import DjangoConnectionField
from graphene_django_plus.models import GuardedModel
from graphene_django_plus.types import ModelType
from graphene_django_plus.fields import CountableConnection
class MyModel(GuardedModel):
class Meta:
# guardian permissions for this model
permissions = [
('can_read', "Can read the this object's info."),
]
name = models.CharField(max_length=255)
class MyModelType(ModelType):
class Meta:
model = MyModel
interfaces = [relay.Node]
# Use our CountableConnection
connection_class = CountableConnection
# When adding this to a query, only objects with a `can_read`
# permission to the request's user will be allowed to return to him
# Note that `can_read` was defined in the model.
# If the model doesn't inherid from `GuardedModel`, `guardian` is not
# installed ot this list is empty, any object will be allowed.
# This is empty by default
object_permissions = [
'can_read',
]
# If unauthenticated users should be allowed to retrieve any object
# of this type. This is not dependant on `GuardedModel` and neither
# `guardian` and is defined as `False` by default
allow_unauthenticated = False
# A list of Django model permissions to check. Different from
# object_permissions, this uses the basic Django's permission system
# and thus is not dependant on `GuardedModel` and neither `guardian`.
# This is an empty list by default.
permissions = []
class Query(graphene.ObjectType):
my_models = DjangoConnectionField(MyModelType)
my_model = relay.Node.Field(MyModelType)
This can be queried like:
# All objects that the user has permission to see
query {
myModels {
totalCount
edges {
node {
id
name
}
}
}
}
# Single object if the user has permission to see it
query {
myModel(id: "<relay global ID>") {
id
name
}
}
Mutations
-
graphene_django_plus.mutations.BaseMutation
: Base mutation usingrelay
and some basic permission checking. Just override its.perform_mutation
to perform the mutation. -
graphene_django_plus.mutations.ModelMutation
: Model mutation capable of both creating and updating a model based on the existence of anid
attribute in the input. All the model's fields will be automatically read from Django, inserted in the input type and validated. -
graphene_django_plus.mutations.ModelCreateMutation
: AModelMutation
enforcing a "create only" rule by excluding theid
field from the input. -
graphene_django_plus.mutations.ModelUpdateMutation
: AModelMutation
enforcing a "update only" rule by making theid
field required in the input. -
graphene_django_plus.mutations.ModelDeleteMutation
: A mutation that will receive only the model's id and will delete it (if given permission, of course).
Here is an example describing how to use those:
import graphene
from graphene import relay
from graphene_django_plus.models import GuardedModel
from graphene_django_plus.types import ModelType
from graphene_django_plus.mutations import (
ModelCreateMutation,
ModelUpdateMutation,
ModelDeleteMutation,
)
class MyModel(GuardedModel):
class Meta:
# guardian permissions for this model
permissions = [
('can_write', "Can update this object's info."),
]
name = models.CharField(max_length=255)
class MyModelType(ModelType):
class Meta:
model = MyModel
interfaces = [relay.Node]
class MyModelUpdateMutation(ModelUpdateMutation):
class Meta:
model = MyModel
# Make sure only users with the given permissions can modify the
# object.
# If the model doesn't inherid from `GuardedModel`, `guardian` is not
# installed ot this list is empty, any object will be allowed.
# This is empty by default.
object_permissions = [
'can_write',
]
# If unauthenticated users should be allowed to retrieve any object
# of this type. This is not dependant on `GuardedModel` and neither
# `guardian` and is defined as `False` by default
allow_unauthenticated = False
# A list of Django model permissions to check. Different from
# object_permissions, this uses the basic Django's permission system
# and thus is not dependant on `GuardedModel` and neither `guardian`.
# This is an empty list by default.
permissions = []
class MyModelDeleteMutation(ModelDeleteMutation):
class Meta:
model = MyModel
object_permissions = [
'can_write',
]
class MyModelCreateMutation(ModelCreateMutation):
class Meta:
model = MyModel
@classmethod
def after_save(cls, info, instance, cleaned_input=None):
# If the user created the object, allow him to modify it
assign_perm('can_write', info.context.user, instance)
class Mutation(graphene.ObjectType):
my_model_create = MyModelCreateMutation.Field()
my_model_update = MyModelUpdateMutation.Field()
my_model_delete = MyModelDeleteMutation.Field()
This can be used to create/update/delete like:
# Create mutation
mutation {
myModelCreate(input: {name: "foobar"}) {
myModel {
name
}
errors {
field
message
}
}
}
# Update mutation
mutation {
myModelUpdate(input: {id: "<relay global ID>" name: "foobar"}) {
myModel {
name
}
errors {
field
message
}
}
}
# Delete mutation
mutation {
myModelDelete(input: {id: "<relay global ID>"}) {
myModel {
name
}
errors {
field
message
}
}
}
Any validation errors will be presented in the errors
return value.
License
This project is licensed under MIT licence (see LICENSE
for more info)
Contributing
Feel free to fork the project and send me pull requests with new features, corrections and translations. We'll gladly merge them and release new versions ASAP.
Project details
Release history Release notifications | RSS feed
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 graphene-django-plus-2.0.tar.gz
.
File metadata
- Download URL: graphene-django-plus-2.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | da57b90cc5f21e48c74cf901d166102e4bcc57811fac69b252381d409a602ae0 |
|
MD5 | e12a5285ff0971d15ace502efe5e2b63 |
|
BLAKE2b-256 | ca9dc8007ae923e0e5c64a38b72ccf5bf0a53ed29e4b2d96feb9f172991ebfd2 |
File details
Details for the file graphene_django_plus-2.0-py2.py3-none-any.whl
.
File metadata
- Download URL: graphene_django_plus-2.0-py2.py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 55c4e7594eeeb370fb6a686b128ef9a8d090fbb84c8a7256afa5be84ba886eef |
|
MD5 | b2bdf809e3997527f37d0fb5f1a9d5e6 |
|
BLAKE2b-256 | e1da88f30dd5e2ccd7aa6acb6eeddc0a50ccf5e294a0051e9d37f3ad3d529a05 |