Skip to content

flavors/django-graphql-extensions

Repository files navigation

Django GraphQL Extensions

Pypi Build Status Codecov Codacy

A collection of custom extensions for Django GraphQL

Dependencies

  • Python ≥ 3.6
  • Django ≥ 2.0
  • Graphene-django ≥ 3.0.0b1

Installation

Install last stable version from Pypi.

pip install django-graphql-extensions

Authentication

  • @login_required
  • @staff_member_required
  • @superuser_required
  • @permission_required
  • @user_passes_test

See the documentation to know the full list of decorators.

from django.contrib.auth import get_user_model

import graphene
from graphql_extensions.decorators import (
    login_required, staff_member_required,
)


class Query(graphene.ObjectType):
    viewer = graphene.Field(UserType)
    users = graphene.List(UserType)

    @login_required
    def resolve_viewer(self, info, **kwargs):
        return info.context.user

    @staff_member_required
    def resolve_users(self, info, **kwargs):
        return get_user_model().objects.all()

Errors

Returning appropriate error responses and masking error messages sent to the client.

Configure your GraphQLView.

from django.urls import include, path

from graphql_extensions.views import GraphQLView

urlpatterns = [
    path('', GraphQLView.as_view(), name='index'),
]

Exceptions

from graphql_extensions import exceptions
  • exceptions.GraphQLError
  • exceptions.PermissionDenied
  • exceptions.ValidationError
  • exceptions.NotFound

Payload

{
  "errors": [
    {
      "message": "You do not have permission to perform this action",
      "locations": [
        {
          "line": 3,
          "column": 13
        }
      ],
      "path": [
        "viewer"
      ],
      "extensions": {
        "type": "PermissionDenied",
        "code": "permissionDenied",
        "timestamp": 1622783872,
        "data": {},
        "operation": "QUERY",
        "trace": [
          "  File \"site-packages/graphql/execution/execute.py\", line 617, in resolve_field\n    result = resolve_fn(source, info, **args)\n",
          "  File \"graphql_extensions/decorators.py\", line 23, in wrapper\n    return func(info.context, *args, **kwargs)\n",
          "  File \"graphql_extensions/decorators.py\", line 35, in wrapper\n    raise exc\n"
        ]
      }
    }
  ],
  "data": {
    "viewer": null
  }
}

Writing tests

This package includes a subclass of unittest.TestCase SchemaTestCase and improve support for making GraphQL queries.

from django.contrib.auth import get_user_model

from graphql_extensions.test import SchemaTestCase


class UsersTests(SchemaTestCase):

    def test_create_user(self):
        query = '''
        mutation CreateUser($username: String!, $password: String!) {
          createUser(username: $username, password: $password) {
            user {
              id
            }
          }
        }'''

        response = self.client.execute(query, {
            'username': 'test',
            'password': 'dolphins',
        })

        self.assertFalse(response.errors)
        self.assertTrue(response.data['user'])

    def test_viewer(self):
        user = get_user_model().objects.create_user(
            username='test',
            password='dolphins',
        )

        self.client.authenticate(self.user)

        query = '''
        {
          viewer {
            username
          }
        }'''

        response = self.client.execute(query)
        data = response.data['viewer']

        self.assertEqual(data['username'], user.username)

Types

Custom Graphene types.

  • Email
  • Timestamp