Skip to content

Commit 12dc8c8

Browse files
author
Ernesto Perez Amigo
committed
Add queryset options to DjangoListObjectType Meta class for specify wanted model queryset.
Add AuthenticatedGraphQLView on graphene_django_extras.views for use 'permission', 'authorization' and 'throttle' classes based on the DRF settings. Special thanks to [@jacobh](https://github.com/jacobh) for this [comment](graphql-python/graphene#249 (comment))
1 parent c6236f9 commit 12dc8c8

File tree

9 files changed

+61
-21
lines changed

9 files changed

+61
-21
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,15 @@ subscription{
445445

446446
## Change Log:
447447

448+
#### v0.1.0-alpha4:
449+
1. Add queryset options to DjangoListObjectType Meta class for specify wanted model queryset.
450+
2. Add AuthenticatedGraphQLView on graphene_django_extras.views for use
451+
'permission', 'authorization' and 'throttle' classes based on the DRF settings. Special thanks to
452+
[@jacobh](https://github.com/jacobh) for this [comment](https://github.com/graphql-python/graphene/issues/249#issuecomment-300068390)
453+
448454
#### v0.1.0-alpha3:
449-
1. Fixed bug on subscriptions when not specified any field in "data" parameter to bean return on notification message.
455+
1. Fixed bug on subscriptions when not specified any field in "data" parameter to bean return on notification
456+
message.
450457

451458
#### v0.1.0-alpha2:
452459
1. Fixed bug when subscribing to a given action (create, update pr delete).

README.rst

+8-1
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,17 @@ For unsubscribe you must send a graphql subscription request like this:
484484
Change Log:
485485
-----------
486486

487+
**************
488+
v0.1.0-alpha4:
489+
**************
490+
1. Add **queryset** options to **DjangoListObjectType** Meta class for specify wanted model queryset.
491+
2. Add AuthenticatedGraphQLView on graphene_django_extras.views for use 'permission', 'authorization' and 'throttle' classes based on the DRF settings. Special thanks to `@jacobh <https://github.com/jacobh>`_ for this `comment <https://github.com/graphql-python/graphene/issues/249#issuecomment-300068390>`_.
492+
487493
**************
488494
v0.1.0-alpha3:
489495
**************
490-
1. Fixed bug on subscriptions when not specified any field in "data" parameter to bean return on notification message.
496+
1. Fixed bug on subscriptions when not specified any field in "data" parameter to bean return on
497+
notification message.
491498

492499
**************
493500
v0.1.0-alpha2:

graphene_django_extras/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .types import DjangoObjectType, DjangoInputObjectType, DjangoListObjectType
99
from .subscriptions import *
1010

11-
VERSION = (0, 1, 0, 'alpha', '3')
11+
VERSION = (0, 1, 0, 'alpha', '4')
1212

1313
__version__ = get_version(VERSION)
1414

graphene_django_extras/fields.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,5 @@ def list_resolver(self, manager, filterset_class, filtering_args, root, info, **
230230
)
231231

232232
def get_resolver(self, parent_resolver):
233-
return partial(self.list_resolver, self.type._meta.model._default_manager,
233+
return partial(self.list_resolver, self.type._meta.queryset or self.type._meta.model._default_manager,
234234
self.filterset_class, self.filtering_args)

graphene_django_extras/subscriptions/mixins.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,5 @@ def serialize_data(self, instance):
4141
data = self.get_serializer(instance).data
4242
only_fields = hasattr(self.get_serializer_class().Meta, 'only_fields')
4343
if only_fields:
44-
if self.get_serializer_class().Meta.only_fields != ['all_fields']:
45-
data = {k: v for k, v in data.items() if k in self.get_serializer_class().Meta.only_fields}
44+
data = {k: v for k, v in data.items() if k in self.get_serializer_class().Meta.only_fields}
4645
return data

graphene_django_extras/subscriptions/subscription.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ def __init_subclass_with_meta__(cls, mutation_class=None, stream=None, queryset=
7777

7878
serializer_fields = [(to_snake_case(field.strip('_')).upper(), to_snake_case(field))
7979
for field in _meta.serializer_class.Meta.fields]
80-
model_fields_enum = Enum('{}Fields'.format(mutation_class._meta.model.__name__),
81-
serializer_fields + [('ALL_FIELDS', 'all_fields')],
80+
model_fields_enum = Enum('{}Fields'.format(mutation_class._meta.model.__name__), serializer_fields,
8281
description=_('Desired {} fields in subscription\'s notification. You can specify '
8382
'"all_fields" value.').format(mutation_class._meta.model.__name__))
8483

graphene_django_extras/types.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from collections import OrderedDict
33

4+
from django.db.models import QuerySet
45
from django.utils.functional import SimpleLazyObject
56
from django.utils.translation import ugettext_lazy as _
67
from graphene import Field, InputField, ObjectType, Int
@@ -23,6 +24,7 @@ class DjangoObjectOptions(BaseOptions):
2324
input_fields = None
2425
interfaces = ()
2526
model = None
27+
queryset = None
2628
registry = None
2729
connection = None
2830
create_container = None
@@ -165,7 +167,7 @@ class Meta:
165167
@classmethod
166168
def __init_subclass_with_meta__(cls, model=None, results_field_name=None, pagination=None,
167169
only_fields=(), exclude_fields=(), filter_fields=None,
168-
interfaces=(), **options):
170+
queryset=None, interfaces=(), **options):
169171

170172
assert is_valid_django_model(model), (
171173
'You need to pass a valid Django Model in {}.Meta, received "{}".'
@@ -174,6 +176,11 @@ def __init_subclass_with_meta__(cls, model=None, results_field_name=None, pagina
174176
if not DJANGO_FILTER_INSTALLED and filter_fields:
175177
raise Exception("Can only set filter_fields if Django-Filter is installed")
176178

179+
assert isinstance(queryset, QuerySet) or queryset is None, (
180+
'The attribute queryset in {} needs to be an instance of '
181+
'Django model queryset, received "{}".'
182+
).format(cls.__name__, queryset)
183+
177184
results_field_name = results_field_name or 'results'
178185

179186
baseType = get_global_registry().get_type_for_model(model)
@@ -200,6 +207,7 @@ def __init_subclass_with_meta__(cls, model=None, results_field_name=None, pagina
200207

201208
_meta = DjangoObjectOptions(cls)
202209
_meta.model = model
210+
_meta.queryset = queryset
203211
_meta.baseType = baseType
204212
_meta.results_field_name = results_field_name
205213
_meta.filter_fields = filter_fields

graphene_django_extras/utils.py

+4-12
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ def get_model_fields(model):
2121
list(model._meta.local_many_to_many) +
2222
list(model._meta.virtual_fields))
2323
]
24-
"""
25-
local_fields = [
26-
(field.name, field)
27-
for field
28-
in sorted(list(model._meta.fields) +
29-
list(model._meta.local_many_to_many))
30-
]
31-
"""
3224

3325
# Make sure we don't duplicate local fields with "reverse" version
3426
local_field_names = [field[0] for field in local_fields]
@@ -249,9 +241,9 @@ def queryset_factory(manager, fields_asts=None, fragments=None, **kwargs):
249241
prefetch_related)
250242

251243
if select_related and prefetch_related:
252-
return manager.select_related(*select_related).prefetch_related(*prefetch_related)
244+
return _get_queryset(manager.select_related(*select_related).prefetch_related(*prefetch_related))
253245
elif not select_related and prefetch_related:
254-
return manager.prefetch_related(*prefetch_related)
246+
return _get_queryset(manager.prefetch_related(*prefetch_related))
255247
elif select_related and not prefetch_related:
256-
return manager.select_related(*select_related)
257-
return manager.get_queryset()
248+
return _get_queryset(manager.select_related(*select_related))
249+
return _get_queryset(manager)

graphene_django_extras/views.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
from graphene_django.views import GraphQLView
3+
from rest_framework.decorators import (authentication_classes, permission_classes, api_view, throttle_classes)
4+
from rest_framework.permissions import IsAuthenticated
5+
from rest_framework.request import Request
6+
from rest_framework.settings import api_settings
7+
from rest_framework.views import APIView
8+
9+
10+
class AuthenticatedGraphQLView(GraphQLView, APIView):
11+
"""
12+
Extra Graphql view that use 'permission', 'authorization' and 'throttle' classes based on the DRF settings.
13+
Thanks to @jacobh in (https://github.com/graphql-python/graphene/issues/249#issuecomment-300068390)
14+
"""
15+
def parse_body(self, request):
16+
if isinstance(request, Request):
17+
return request.data
18+
return super(AuthenticatedGraphQLView, self).parse_body(request)
19+
20+
@classmethod
21+
def as_view(cls, *args, **kwargs):
22+
view = super(AuthenticatedGraphQLView, cls).as_view(*args, **kwargs)
23+
view = permission_classes((IsAuthenticated,))(view)
24+
view = authentication_classes(api_settings.DEFAULT_AUTHENTICATION_CLASSES)(view)
25+
view = throttle_classes(api_settings.DEFAULT_THROTTLE_CLASSES)(view)
26+
view = api_view(['GET', 'POST'])(view)
27+
28+
return view

0 commit comments

Comments
 (0)