django-graphql-bp
Boiler plate for API projects based on Django 2 & graphql (graphene) 2
Requirments
- python: 3.5+
- pip: 9.0+
- postgress: 9.5+
Configuration
Settings and Environment variables
-
Environment vasriables:
- DB_NAME - database name;
- DB_USER - database username;
- DB_PASSWORD - database user's password;
- DB_HOST - database host;
- DB_PORT - database port.
In config file:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ['DB_NAME'], 'USER': os.environ['DB_USER'], 'PASSWORD': os.environ['DB_PASSWORD'], 'HOST': os.environ['DB_HOST'], 'PORT': os.environ['DB_PORT'], } }
-
Test e-mailbox:
Email address wherewhere tests will spam with emails.
Environment variables:
- TEST_EMAIL_USERNAME - email username;
- TEST_EMAIL_DOMAIN - email domain;
Where email have following structure TEST_EMAIL_USERNAME@TEST_EMAIL_DOMAIN. For example test@gmail.com: TEST_EMAIL_USERNAME="test" and TEST_EMAIL_DOMAIN="gmail.com".
In config file:
# Test email of the next structure: TEST_EMAIL_USERNAME@TEST_EMAIL_DOMAIN TEST_EMAIL_USERNAME = os.environ.get('TEST_EMAIL_USERNAME') TEST_EMAIL_DOMAIN = os.environ.get('TEST_EMAIL_DOMAIN')
-
User app:
In config file:
INSTALLED_APPS = [ ... 'django_graphql_bp.user', ... ] # Custom User model AUTH_USER_MODEL = 'user.User'
This User model will be used instead of standard django.contrib.auth.models.User.
-
Article app (optional): In config file:
INSTALLED_APPS = [ ... 'django_graphql_bp.article', ... ]
Configure it only if willing to use article app's featurues.
-
Graphql:
In config file:
INSTALLED_APPS = [ ... 'graphene_django', ... ] # Path to root directory of the project PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) GRAPHENE = { # where Schema class is located 'SCHEMA': 'app.graphql.api.schema' }
-
AWS S3 storage (optional):
Environment variables:
- AWS_ACCESS_KEY_ID - Access Key ID from AWS ;
- AWS_SECRET_ACCESS_KEY - Secret Access Key from AWS ;
- AWS_STORAGE_BUCKET_NAME - name of backet in AWS S3 account;
- AWS_MEDIA_BUCKET_NAME - name of backet in AWS S3 account;
- AWS_QUERYSTRING_AUTH - set string 'False' to override default.
In config file:
# Amazon S3 configuration AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY') AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME') AWS_MEDIA_BUCKET_NAME = os.environ.get('AWS_MEDIA_BUCKET_NAME') AWS_QUERYSTRING_AUTH = ast.literal_eval(os.environ.get('AWS_QUERYSTRING_AUTH')) AWS_S3_OBJECT_PARAMETERS = {'CacheControl': 'max-age=86400'} # Django file storage DEFAULT_FILE_STORAGE = 'django_graphql_bp.core.storages.S3MediaStorage'
Installation
-
Package:
To install run:
# pip install django-graphql-bp
Or add django-graphql-bp package to your requirements and run from there. If you are using virtual environment, make sure that you are activated it before run. Package will install following packages:
- boto3 1.5+
- django 2.0+
- django-filter 1.1+
- graphene-django 2.0+
- pillow 5.0+
- psycopg2 2.7+
-
Database migrations:
Use standard django migration to install custom user model:
# ./manage.py migrate
-
Url for graphql:
In urls.py:
from django.views.decorators.csrf import csrf_exempt from graphene_django.views import GraphQLView urlpatterns = [ path('graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))), ]
-
Schema:
To use all User's operations from package need to extend Queries and Mutations from UserQueries and UserMutations from django_graphql_bp.graphql.api. api.py file example:
import graphene import django_graphql_bp.article.schema # required to use article operations import django_graphql_bp.user.schema class Queries( django_graphql_bp.article.schema.Query, # required to use article queries django_graphql_bp.user.schema.Query, graphene.ObjectType ): pass class Mutations( django_graphql_bp.article.schema.Mutation, # required to use article mutations django_graphql_bp.user.schema.Mutation, graphene.ObjectType ): pass schema = graphene.Schema(query=Queries, mutation=Mutations)
Location of api.py file has been set up at Configuration #5
-
Tests To enable tests for all User's and Article's operations from package. test.py example:
from django_graphql_bp.article.tests import * # to enable Article tests from django_graphql_bp.user.tests import * # to enable User tests
get_schema allow tests use Schema from application instead of Schema from package
Usage
-
Common:
List of common usages:
-
ok (bool) - boolean success flag for mutations that not threw any exceptions.
-
node (object) - object related to certain Django model contains all fields and relations that wasn't excluded.
-
validationErrors (object) - JSON object with validation errors of following structure:
{ fieldname1: [ {code: "error code 1", message: "error message 1"}, ... ], ... }
-
edges (object) - array object of nodes (Usage #2):
{ node { // node data } }
-
errors - array of error objects of following structure:
[ { "message": "error message", "locations": [ { "line": (int), // line of error "column": (int) // column of error } ] } ]
-
-
CRUD mutations:
coming soon...
-
User operations:
-
Create mutation:
mutation { createUser(input: { email: "email@email.com" password1: "password" password2: "password" }) { ok node { pk } validationErrors } }
Access:
- guest;
- any user;
Input:
- email (required) - string;
- password (required) - string.
Output:
- ok - Usage #1.1;
- node - User object (with password field excluded) - Usage #1.2;
- validationErrors - Usage #1.3.
-
Update mutation:
mutation { updateUser(input: { pk: 1 email: "email@email.com" name: "name" isActive: true }) { ok node { pk } validationErrors } }
Access:
- user to own record;
- staff user.
Input:
- pk (required) - int;
- email (optional) - string;
- name (optional) - string;
- isActive (optional) - bool.
Output:
- ok - Usage #1.1;
- node - User object (with password field excluded) - Usage #1.2;
- validationErrors - Usage #1.3.
-
Delete mutation:
mutation { deleteUser(input: { pk: 1 }) { ok node { pk } } }
Access:
- user to own record;
- staff user.
Input:
- pk (required) - int.
Output:
- ok - Usage #1.1;
- node - User object (with password field excluded) - Usage #1.2.
-
Login mutation:
mutation { loginUser(input: { email: "email@email.com" password: "password" }) { ok node { pk } validationErrors } }
Access:
- guest;
- any user.
Input:
- email (required) - string;
- password (required) - string.
Output:
- ok - Usage #1.1;
- node - User object (with password field excluded) - Usage #1.2;
- validationErrors - Usage #1.3.
-
Logout mutation:
mutation { logoutUser(input: {}) { ok node { pk } } }
Access:
- guest;
- any user.
Input:
- None
Output:
- ok - Usage #1.1;
- node - User object (with password field excluded) - Usage #1.2.
-
Current user query:
query { currentUser { pk } }
Access:
- guest;
- any user.
Output:
- node - User object (with password field excluded) - Usage #1.2.
-
Users query:
query { users { edges { node { pk } } } }
Access:
- staff member.
Output:
- edges - of User objects - Usage #1.4.
-