Easy to use abstraction layer for GraphQL, with support for Django ORM.
Project description
Easy GraphQL Server
easy_graphql_server provides an easy way to expose a database in GraphQL, using ORM models and web frameworks (so far only Django is supported, but SQLAlchemy & Flask will soon come).
- Easy GraphQL Server
easy_graphql_server can be installed from PyPI using the built-in pip command:
pip install easy-graphql-server
Usage
Expose methods
There are three ways to expose a method in the GraphQL schema.
Calling Schema.expose_query() and Schema.expose_mutation()
import easy_graphql_server as egs
schema = egs.Schema()
schema.expose_query(
name = 'foo',
input_format = {
'input_string': egs.Required(str),
'input_integer': int,
},
output_format = {
'output_string': str,
'output_integer': int,
},
method = lambda input_string, input_integer=None: {
'output_string': 2 * input_string,
'output_integer': None if input_integer is None else 2 * input_integer,
},
)
_internal_value = 0
def bar_mutation_method(value=None, increment_value=None):
if value is not None:
_internal_value = value
if increment_value is not None:
_internal_value += increment_value
return {
'value': _internal_value,
}
schema.expose_mutation(
name = 'bar',
input_format = {
'input_string': egs.Required(str),
'input_integer': int,
},
output_format = {
'output_string': str,
'output_integer': int,
},
method = bar_mutation_method,
)
Subclassing Schema.ExposedQuery and Schema.ExposedMutation
import easy_graphql_server as egs
schema = egs.Schema()
class FooQuery(schema.ExposedQuery):
name = 'foo'
input_format = {
'input_string': egs.Required(str),
'input_integer': int,
}
output_format = {
'output_string': str,
'output_integer': int,
}
@staticmethod
def method(input_string, input_integer=None):
return {
'output_string': 2 * input_string,
'output_integer': None if input_integer is None else 2 * input_integer,
}
class BarMutation(schema.ExposedMutation):
name = 'bar'
_internal_value = 0
input_format = {
'value': int,
'increment_value': int,
}
output_format = {
'value': int,
}
@classmethod
def method(cls, value=None, increment_value=None):
if value is not None:
cls._internal_value = value
if increment_value is not None:
cls._internal_value += increment_value
return {
'value': cls._internal_value,
}
Subclassing easy_graphql_server.ExposedQuery and easy_graphql_server.ExposedMutation
This is very similar to the previous way.
import easy_graphql_server as egs
class FooQuery(schema.ExposedQuery):
name = 'foo'
input_format = {
'input_string': egs.Required(str),
'input_integer': int,
}
output_format = {
'output_string': str,
'output_integer': int,
}
@staticmethod
def method(input_string, input_integer=None):
return {
'output_string': 2 * input_string,
'output_integer': None if input_integer is None else 2 * input_integer,
}
class BarMutation(schema.ExposedMutation):
name = 'bar'
_internal_value = 0
input_format = {
'value': int,
'increment_value': int,
}
output_format = {
'value': int,
}
@classmethod
def method(cls, value=None, increment_value=None):
if value is not None:
cls._internal_value = value
if increment_value is not None:
cls._internal_value += increment_value
return {
'value': cls._internal_value,
}
schema = egs.Schema()
schema.expose(FooQuery)
schema.expose(BarMutation)
Available options for exposing methods
The same options can be passed either as class attributes for subclasses of Schema.ExposedQuery and Schema.ExposedMutation, or as keyword arguments to Schema.expose_query() and Schema.expose_mutation() methods.
Options for queries and mutations are the same.
-
nameis the name under which the method shall be exposed -
methodis the callback function of your choice -
input_formatis the input format for the GraphQL method, passed as a (possibly recursive) mapping; if unspecified orNone, the defined GraphQL method will take no input; the mapping keys are -
output_formatis the output format of the GraphQL method, passed as a (possibly recursive) mapping or as alistcontaining one mapping -
pass_graphql_selectioncan either be aboolor astr; if set toTrue, thegraphql_selectionparameter will be passed to the callback method, indicating which fields are requested for output; if set to astr, the given string will be the name of the keyword parameter passed to the callback method instead ofgraphql_selection -
pass_graphql_pathcan either be aboolor astr; if set toTrue, thegraphql_pathparameter will be passed to the callback method, indicating as alist[str]the GraphQL path in which the method is being executed; if set to astr, the given string will be the name of the keyword parameter passed to the callback method instead ofgraphql_path -
pass_authenticated_usercan either be aboolor astr; if set toTrue, theauthenticated_userparameter will be passed to the callback method, indicating the user authenticated in the source HTTP request (orNoneif the request was unauthenticated); if set to astr, the given string will be the name of the keyword parameter passed to the callback method instead ofauthenticated_user -
require_authenticated_useris aboolindicating whether or not authentication is required for the exposed method
Expose ORM models
What does it do?
For instance, exposing a model called Thing will expose the following queries...
thing: fetch a single instance of the model given its unique identifierthings: fetch a collection of model instances, given filtering criteria, or unfiltered, paginated or not
...and mutations:
create_thing: create a single instance of the model given the data to be insertedupdate_thing: update a single instance of the model given its unique identifier and a mapping the new data to applydelete_thing: delete a single instance of the model given its unique identifier
Calling Schema.expose_model()
import easy_graphql_server
from my_django_application.models import Person
schema = easy_graphql_server.Schema()
schema.expose_model(
orm_model=Person,
plural_name='people',
can_expose=('id', 'first_name', 'last_name'),
cannot_write=('id',),
)
Subclassing Schema.ExposedModel
import easy_graphql_server
from my_django_application.models import Person
schema = easy_graphql_server.Schema()
class ExposedPerson(schema.ExposedModel):
orm_model = Person
plural_name = 'people'
can_expose = ('id', 'first_name', 'last_name')
cannot_write = ('id',)
Subclassing easy_graphql_server.ExposedModel
This is very similar to the previous way.
import easy_graphql_server
from my_django_application.models import Person
schema = easy_graphql_server.Schema()
class ExposedPerson(easy_graphql_server.ExposedModel):
orm_model = Person
plural_name = 'people'
can_expose = ('id', 'first_name', 'last_name')
cannot_write = ('id',)
schema = easy_graphql_server.Schema()
schema.expose(ExposedPerson)
Available options for exposing models
The same options can be passed either as class attributes for subclasses of ExposedModel, or as keyword arguments to Schema.expose_model() method.
-
cannot_exposeis either abool, or atuple[str]; defaults toFalse; if set toTrue, no query or mutation method will be exposed for the model; if set to a list of field names, those fields will be excluded from every query and mutation -
can_createis either abool, or atuple[str]; defaults toTrue; if set toFalse, no creation mutation method will be exposed for the model; if set to a list of field names, only those fields will be possible field values passed at insertion time tocreate_... -
cannot_createis either abool, or atuple[str]; defaults toFalse; if set toTrue, no creation mutation method will be exposed for the model; if set to a list of field names, those fields will be excluded from possible field values passed at insertion time tocreate_... -
can_readis either abool, or atuple[str]; defaults toTrue; if set toFalse, no query method will be exposed for the model; if set to a list of field names, only those fields will be exposed for the...(show one instance) and...s(show a collection of instances) queries (it also defines which fields are available as mutations results) -
cannot_readis either abool, or atuple[str]; defaults toFalse; if set toTrue, no query method will be exposed for the model; if set to a list of field names, only those fields will be exposed for the...(show one instance) and...s(show a collection of instances) queries (it also defines which fields are not available as mutations results) -
can_updateis either abool, or atuple[str]; defaults toTrue; if set toTrue, nodelete_...mutation method will be exposed for the model; if set to a list of field names, those fields will be the only possible keys for the_parameter (new data for instance fields) of theupdate_...mutation -
cannot_updateis either abool, or atuple[str]; defaults toFalse; if set toTrue, noupdate_...mutation method will be exposed for the model; if set to a list of field names, those fields will be excluded from possible keys for the_parameter (new data for instance fields) of theupdate_...mutation -
can_deleteis abool; defaults toTrue; if set toFalse, nodelete_...mutation method will be exposed for the model -
cannot_deleteis abool; defaults toFalse; if set toTrue, nodelete_...mutation method will be exposed for the model -
only_when_child_ofis eitherNone(model does not have to be nested to be exposed),True(the model is not exposed if not nested), an ORM model class, or a tuple/list/set of ORM model classes (the defined model can only be exposed when nested directly under one of models passed asonly_when_child_ofparameter) -
require_authenticated_useris aboolindicating whether or not authentication is required for the exposed method -
has_permissionis eitherNone, or a callback method returning abool(Trueif operation is authorized,Falseotherwise), and taking as parametersauthenticated_user(self-explanatory),operation(a value of theeasy_graphql_server.Operationenum:CREATE,READ,UPDATEorDELETE) anddata(new data, only applies toCREATEandUPDATE) -
filter_for_useris eitherNone, or a callback method returning aqueryset, and taking as parametersquerysetandauthenticated_user
Perform GraphQL queries
If you want to perform GraphQL queries on the schema without going through a schema, you can use Schema.execute(). This method can take the following parameters:
query: the GraphQL query, in the form of astrvariables: variables to go along with the query (optional), as adict[str,Any]operation_name: name of the operation to be executed within the query (optional)authenticated_user: parameter that will be passed to the callback functions of GraphQL methods that require it (optional)serializable_output: the output will be rendered as JSON-serializabledict, instead of agraphql.execution.execute.ExecutionResultinstance
Credits and history
The easy_graphql_server library was originally a subproject within the Bridger development team, to provide an easy way to expose database models with GraphQL using Graphene.
The project was then rewritten with graphq-core and Graphene was dropped.
License
easy_graphql_server is under MIT license.
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
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file easy_graphql_server-0.9.31.tar.gz.
File metadata
- Download URL: easy_graphql_server-0.9.31.tar.gz
- Upload date:
- Size: 41.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da6302487e6ac1d5a094c361eb9c31de5bee7a0f21f883494501828d37fc61ac
|
|
| MD5 |
62387fad534f3f44b6e588e2db6d905b
|
|
| BLAKE2b-256 |
77e5d50d9c25c77d2b3368f5c35c8dcff0e0905e70166bacbab21c0ccc97d6db
|
File details
Details for the file easy_graphql_server-0.9.31-py3-none-any.whl.
File metadata
- Download URL: easy_graphql_server-0.9.31-py3-none-any.whl
- Upload date:
- Size: 46.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.10.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3b72f66cdd30d6204e25d601f89b6ad0df061e04623aacd5259517a0cbd13d8
|
|
| MD5 |
fad3951cebe0eda9b4375aebde6ac86b
|
|
| BLAKE2b-256 |
42252b79d4f56748505c4397b6756c2404d9c961065848c083684eb90701cb4d
|