# Path: graphene_django_extras/settings.py
# DEFAULTS = {
#     # Pagination
#     "DEFAULT_PAGINATION_CLASS": None,  # 'graphene_django_extras.paginations.LimitOffsetGraphqlPagination'
#     "DEFAULT_PAGE_SIZE": None,
#     "MAX_PAGE_SIZE": None,
#     "CLEAN_RESPONSE": False,
#     "CACHE_ACTIVE": False,
#     "CACHE_TIMEOUT": 300,  # seconds (default 5 min)
# }
# IMPORT_STRINGS = ("DEFAULT_PAGINATION_CLASS",)
#     MODULE_DOC = "https://github.com/eamigo86/graphene-django-extras"
# class GraphQLAPISettings(APISettings):
#     def user_settings(self):
# def reload_graphql_api_settings(*args, **kwargs):
# 
# Path: graphene_django_extras/utils.py
# def clean_dict(d):
#     """
#     Remove all empty fields in a nested dict
#     """
# 
#     if not isinstance(d, (dict, list)):
#         return d
#     if isinstance(d, list):
#         return [v for v in (clean_dict(v) for v in d) if v]
#     return OrderedDict(
#         [(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v]
#     )


import hashlib
from django.core.cache import caches
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
from graphql import Source, parse, execute
from graphql.execution.executor import subscribe
from graphql.utils.get_operation_ast import get_operation_ast
from rest_framework.decorators import (
    authentication_classes,
    permission_classes,
    api_view,
    throttle_classes,
)
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rx import Observable
from .settings import graphql_api_settings
from .utils import clean_dict
    def fetch_cache_key(request):
        """ Returns a hashed cache key. """
        m = hashlib.md5()
        m.update(request.body)

        return m.hexdigest()

    def super_call(self, request, *args, **kwargs):
        response = super(ExtraGraphQLView, self).dispatch(request, *args, **kwargs)

        return response

    def dispatch(self, request, *args, **kwargs):
        """ Fetches queried data from graphql and returns cached & hashed key. """
        if not graphql_api_settings.CACHE_ACTIVE:
            return self.super_call(request, *args, **kwargs)

        cache = caches["default"]
        operation_ast = self.get_operation_ast(request)
        if operation_ast and operation_ast.operation == "mutation":
            cache.clear()
            return self.super_call(request, *args, **kwargs)

        cache_key = "_graplql_{}".format(self.fetch_cache_key(request))
        response = cache.get(cache_key)

        if not response:
            response = self.super_call(request, *args, **kwargs)

            # cache key and value

# Path: graphene_django_extras/settings.py
# DEFAULTS = {
#     # Pagination
#     "DEFAULT_PAGINATION_CLASS": None,  # 'graphene_django_extras.paginations.LimitOffsetGraphqlPagination'
#     "DEFAULT_PAGE_SIZE": None,
#     "MAX_PAGE_SIZE": None,
#     "CLEAN_RESPONSE": False,
#     "CACHE_ACTIVE": False,
#     "CACHE_TIMEOUT": 300,  # seconds (default 5 min)
# }
# IMPORT_STRINGS = ("DEFAULT_PAGINATION_CLASS",)
#     MODULE_DOC = "https://github.com/eamigo86/graphene-django-extras"
# class GraphQLAPISettings(APISettings):
#     def user_settings(self):
# def reload_graphql_api_settings(*args, **kwargs):
# 
# Path: graphene_django_extras/utils.py
# def clean_dict(d):
#     """
#     Remove all empty fields in a nested dict
#     """
# 
#     if not isinstance(d, (dict, list)):
#         return d
#     if isinstance(d, list):
#         return [v for v in (clean_dict(v) for v in d) if v]
#     return OrderedDict(
#         [(k, v) for k, v in ((k, clean_dict(v)) for k, v in list(d.items())) if v]
#     )


# Path: graphene_django_extras/views.py
import hashlib
from django.core.cache import caches
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
from graphql import Source, parse, execute
from graphql.execution.executor import subscribe
from graphql.utils.get_operation_ast import get_operation_ast
from rest_framework.decorators import (
    authentication_classes,
    permission_classes,
    api_view,
    throttle_classes,
)
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from rx import Observable
from .settings import graphql_api_settings
from .utils import clean_dict

    def fetch_cache_key(request):
        """ Returns a hashed cache key. """
        m = hashlib.md5()
        m.update(request.body)

        return m.hexdigest()

    def super_call(self, request, *args, **kwargs):
        response = super(ExtraGraphQLView, self).dispatch(request, *args, **kwargs)

        return response

    def dispatch(self, request, *args, **kwargs):
        """ Fetches queried data from graphql and returns cached & hashed key. """
        if not graphql_api_settings.CACHE_ACTIVE:
            return self.super_call(request, *args, **kwargs)

        cache = caches["default"]
        operation_ast = self.get_operation_ast(request)
        if operation_ast and operation_ast.operation == "mutation":
            cache.clear()
            return self.super_call(request, *args, **kwargs)

        cache_key = "_graplql_{}".format(self.fetch_cache_key(request))
        response = cache.get(cache_key)

        if not response:
            response = self.super_call(request, *args, **kwargs)

            # cache key and value

            cache.set(cache_key, response, timeout=graphql_api_settings.CACHE_TIMEOUT)