Skip to content

Commit 428b6da

Browse files
author
Ernesto Perez Amigo
committed
1. Added Binary graphql type. A BinaryArray is used to convert a Django BinaryField to the string form.
2. Added 'CACHE_ACTIVE' and 'CACHE_TIMEOUT' config options to GRAPHENE_DJANGO_EXTRAS settings for activate cache and define a expire time. Default values are: CACHE_ACTIVE=False, CACHE_TIMEOUT=300 (seconds). Only available for Queries. 3. Updated Date directive for use with Django TimeField, DateField, and DateTimeField. 4. Updated ExtraGraphQLView and AuthenticatedGraphQLView to allow use subscription requests on graphene-django >=2.0 5. Updated setup dependence to graphene-django>=2.0.
1 parent 013be3b commit 428b6da

File tree

9 files changed

+259
-81
lines changed

9 files changed

+259
-81
lines changed

README.md

+16-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ This package add some extra functionalities to graphene-django to facilitate the
99
2. Allows to define DjangoRestFramework serializers based Mutations.
1010
3. Allows use Directives on Queries and Fragments.
1111

12-
**NOTE:** Subscription support was moved to [graphene-django-subscriptions](https://github.com/eamigo86/graphene-django-subscriptions) due incompatibility with subscriptions on graphene-django>=2.0
12+
**NOTE:** Subscription support was moved to [graphene-django-subscriptions](https://github
13+
.com/eamigo86/graphene-django-subscriptions).
1314

1415
## Installation
1516

@@ -52,6 +53,8 @@ for DjangoListObjectType classes pagination definitions on settings.py like this
5253
'DEFAULT_PAGINATION_CLASS': 'graphene_django_extras.paginations.LimitOffsetGraphqlPagination',
5354
'DEFAULT_PAGE_SIZE': 20,
5455
'MAX_PAGE_SIZE': 50,
56+
'CACHE_ACTIVE': True,
57+
'CACHE_TIMEOUT': 300 # seconds
5558
}
5659
```
5760

@@ -468,9 +471,6 @@ And we get this output data:
468471
```
469472
As we see, the directives is a easy way to format output data on queries, and it's can be put together like a chain.
470473

471-
**IMPORTANT NOTE**: The *date* directive only work with datetime returned as String Type and take a string of tokens,
472-
this tokens are the common of JavaScript date format.
473-
474474
**List of possible date's tokens**:
475475
"YYYY", "YY", "WW", "W", "DD", "DDDD", "d", "ddd", "dddd", "MM", "MMM", "MMMM", "HH", "hh", "mm", "ss", "A", "ZZ", "z".
476476

@@ -483,6 +483,18 @@ You can use this shortcuts too:
483483

484484
## Change Log:
485485

486+
#### v0.3.0:
487+
1. Added Binary graphql type. A BinaryArray is used to convert a Django BinaryField to the string form.
488+
2. Added 'CACHE_ACTIVE' and 'CACHE_TIMEOUT' config options to GRAPHENE_DJANGO_EXTRAS settings for activate cache and
489+
define a expire time. Default values are: CACHE_ACTIVE=False, CACHE_TIMEOUT=300 (seconds). Only available for
490+
Queries.
491+
3. Updated Date directive for use with Django TimeField, DateField, and DateTimeField.
492+
4. Updated ExtraGraphQLView and AuthenticatedGraphQLView to allow use subscription requests on graphene-django >=2.0
493+
5. Updated setup dependence to graphene-django>=2.0.
494+
495+
#### v0.2.2:
496+
1. Fixed performance bug on some queries when request nested ManyToMany fields.
497+
486498
#### v0.2.1:
487499
1. Fixed bug with default PaginationClass and DjangoFilterPaginateListField.
488500

README.rst

+17-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This package add some extra functionalities to **graphene-django** to facilitate
77
2. Allows to define DjangoRestFramework serializers based Mutations.
88
3. Allows use Directives on Queries and Fragments.
99

10-
**NOTE:** Subscription support was moved to `graphene-django-subscriptions <https://github.com/eamigo86/graphene-django-subscriptions>`_ due incompatibility with subscriptions on graphene-django>=2.0
10+
**NOTE:** Subscription support was moved to `graphene-django-subscriptions <https://github.com/eamigo86/graphene-django-subscriptions>`_
1111

1212
Installation:
1313
-------------
@@ -55,6 +55,8 @@ DjangoListObjectType classes pagination definitions on settings.py like this:
5555
'DEFAULT_PAGINATION_CLASS': 'graphene_django_extras.paginations.LimitOffsetGraphqlPagination',
5656
'DEFAULT_PAGE_SIZE': 20,
5757
'MAX_PAGE_SIZE': 50,
58+
'CACHE_ACTIVE': True,
59+
'CACHE_TIMEOUT': 300 # seconds
5860
}
5961
6062
********************
@@ -510,9 +512,6 @@ And we get this output data:
510512
511513
As we see, the directives is a easy way to format output data on queries, and it's can be put together like a chain.
512514

513-
**IMPORTANT NOTE**: The *date* directive only work with datetime returned as Graphene String Type not with normal
514-
Graphene DateTime, Time or Date Types and take a string of tokens, this tokens are the common of JavaScript date format.
515-
516515
**List of possible date's tokens**:
517516
"YYYY", "YY", "WW", "W", "DD", "DDDD", "d", "ddd", "dddd", "MM", "MMM", "MMMM", "HH", "hh", "mm", "ss", "A", "ZZ", "z".
518517

@@ -526,6 +525,20 @@ You can use this shortcuts too:
526525
Change Log:
527526
-----------
528527

528+
*******
529+
v0.3.0:
530+
*******
531+
1. Added Binary graphql type. A BinaryArray is used to convert a Django BinaryField to the string form.
532+
2. Added 'CACHE_ACTIVE' and 'CACHE_TIMEOUT' config options to GRAPHENE_DJANGO_EXTRAS settings for activate cache queries result and define a expire time. Default values are: CACHE_ACTIVE=False, CACHE_TIMEOUT=300 (5 minutes).
533+
3. Updated Date directive for use with Django TimeField, DateField, and DateTimeField.
534+
4. Updated ExtraGraphQLView and AuthenticatedGraphQLView to allow use subscription requests on graphene-django >=2.0
535+
5. Updated setup dependence to graphene-django>=2.0.
536+
537+
*******
538+
v0.2.2:
539+
*******
540+
1. Fixed performance bug on some queries when request nested ManyToMany fields.
541+
529542
*******
530543
v0.2.1:
531544
*******

graphene_django_extras/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .paginations import LimitOffsetGraphqlPagination, PageGraphqlPagination, CursorGraphqlPagination
1010
from .types import DjangoObjectType, DjangoInputObjectType, DjangoListObjectType, DjangoSerializerType
1111

12-
VERSION = (0, 2, 2, 'final', '')
12+
VERSION = (0, 3, 0, 'final', '')
1313

1414
__version__ = get_version(VERSION)
1515

graphene_django_extras/base_types.py

+115-35
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import absolute_import
33

4+
import binascii
45
import datetime
5-
import graphene
66

7-
from graphene import Scalar
7+
import graphene
88
from graphene.utils.str_converters import to_camel_case
99
from graphql.language import ast
1010

@@ -17,39 +17,6 @@
1717
)
1818

1919

20-
class Date(Scalar):
21-
'''
22-
The `Date` scalar type represents a Date
23-
value as specified by
24-
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
25-
'''
26-
epoch_time = '00:00:00'
27-
28-
@staticmethod
29-
def serialize(date):
30-
if isinstance(date, datetime.datetime):
31-
date = date.date()
32-
33-
assert isinstance(date, datetime.date), (
34-
'Received not compatible date "{}"'.format(repr(date))
35-
)
36-
return date.isoformat()
37-
38-
@classmethod
39-
def parse_literal(cls, node):
40-
if isinstance(node, ast.StringValue):
41-
return cls.parse_value(node.value)
42-
43-
@classmethod
44-
def parse_value1(cls, value):
45-
dt = iso8601.parse_date('{}T{}'.format(value, cls.epoch_time))
46-
return datetime.date(dt.year, dt.month, dt.day)
47-
48-
@staticmethod
49-
def parse_value(value):
50-
return iso8601.parse_date(value).date()
51-
52-
5320
def object_type_factory(_type, new_model, new_name=None, new_only_fields=(), new_exclude_fields=(),
5421
new_filter_fields=None, new_registry=None, new_skip_registry=False):
5522

@@ -144,3 +111,116 @@ class GenericForeignKeyInputType(graphene.InputObjectType):
144111

145112
class Meta:
146113
description = ' Auto generated InputType for a model\'s GenericForeignKey field '
114+
115+
116+
# ************************************************ #
117+
# ************** CUSTOM BASE TYPES *************** #
118+
# ************************************************ #
119+
class CustomDate(object):
120+
121+
def __init__(self, date):
122+
self.date_str = date
123+
124+
125+
class Binary(graphene.Scalar):
126+
"""
127+
BinaryArray is used to convert a Django BinaryField to the string form
128+
"""
129+
@staticmethod
130+
def binary_to_string(value):
131+
return binascii.hexlify(value).decode("utf-8")
132+
133+
serialize = binary_to_string
134+
parse_value = binary_to_string
135+
136+
@classmethod
137+
def parse_literal(cls, node):
138+
if isinstance(node, ast.StringValue):
139+
return cls.binary_to_string(node.value)
140+
141+
142+
class Time(graphene.Scalar):
143+
"""
144+
The `Time` scalar type represents a Time value as
145+
specified by
146+
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
147+
"""
148+
epoch_date = '1970-01-01'
149+
150+
@staticmethod
151+
def serialize(time):
152+
if isinstance(time, CustomDate):
153+
return time.date_str
154+
155+
assert isinstance(time, datetime.time), (
156+
'Received not compatible time "{}"'.format(repr(time))
157+
)
158+
return time.isoformat()
159+
160+
@classmethod
161+
def parse_literal(cls, node):
162+
if isinstance(node, ast.StringValue):
163+
return cls.parse_value(node.value)
164+
165+
@classmethod
166+
def parse_value(cls, value):
167+
dt = iso8601.parse_date('{}T{}'.format(cls.epoch_date, value))
168+
return datetime.time(dt.hour, dt.minute, dt.second, dt.microsecond, dt.tzinfo)
169+
170+
171+
class Date(graphene.Scalar):
172+
"""
173+
The `Date` scalar type represents a Date
174+
value as specified by
175+
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
176+
"""
177+
epoch_time = '00:00:00'
178+
179+
@staticmethod
180+
def serialize(date):
181+
if isinstance(date, CustomDate):
182+
return date.date_str
183+
184+
if isinstance(date, datetime.datetime):
185+
date = date.date()
186+
187+
assert isinstance(date, datetime.date), (
188+
'Received not compatible date "{}"'.format(repr(date))
189+
)
190+
return date.isoformat()
191+
192+
@classmethod
193+
def parse_literal(cls, node):
194+
if isinstance(node, ast.StringValue):
195+
return cls.parse_value(node.value)
196+
197+
@staticmethod
198+
def parse_value(value):
199+
return iso8601.parse_date(value).date()
200+
201+
202+
class DateTime(graphene.Scalar):
203+
"""
204+
The `DateTime` scalar type represents a DateTime
205+
value as specified by
206+
[iso8601](https://en.wikipedia.org/wiki/ISO_8601).
207+
"""
208+
209+
@staticmethod
210+
def serialize(dt):
211+
if isinstance(dt, CustomDate):
212+
return dt.date_str
213+
214+
assert isinstance(dt, (datetime.datetime, datetime.date)), (
215+
'Received not compatible datetime "{}"'.format(repr(dt))
216+
)
217+
return dt.isoformat()
218+
219+
@classmethod
220+
def parse_literal(cls, node):
221+
if isinstance(node, ast.StringValue):
222+
return cls.parse_value(node.value)
223+
224+
@staticmethod
225+
def parse_value(value):
226+
return iso8601.parse_date(value)

graphene_django_extras/converter.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,20 @@
55
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation, GenericRel
66
from django.db import models
77
from django.utils.encoding import force_text
8-
from graphene import (Field, ID, Boolean, Dynamic, Enum, Float, Int, List, NonNull, String, UUID)
9-
from graphene.types.datetime import DateTime, Time
8+
from graphene import (
9+
Field, ID, Boolean, Dynamic, Enum, Float, Int, List, NonNull, String, UUID
10+
)
1011
from graphene.types.json import JSONString
1112
from graphene.utils.str_converters import to_camel_case, to_const
1213
from graphene_django.compat import ArrayField, HStoreField, RangeField, JSONField
1314
from graphene_django.fields import DjangoListField
1415
from graphene_django.utils import import_single_dispatch
1516

16-
from .base_types import GenericForeignKeyType, GenericForeignKeyInputType
17+
from .base_types import (
18+
GenericForeignKeyType, GenericForeignKeyInputType, DateTime, Time, Date, Binary
19+
)
1720
from .fields import DjangoFilterListField
1821
from .utils import is_required, get_model_fields, get_related_model
19-
try:
20-
from graphene import Date
21-
except ImportError:
22-
from .base_types import Date
2322

2423
singledispatch = import_single_dispatch()
2524

@@ -179,6 +178,12 @@ def convert_field_to_nullboolean(field, registry=None, input_flag=None, nested_f
179178
required=is_required(field) and input_flag == 'create')
180179

181180

181+
@convert_django_field.register(models.BinaryField)
182+
def convert_binary_to_string(field, registry=None, input_flag=None, nested_fields=False):
183+
return Binary(description=field.help_text or field.verbose_name,
184+
required=is_required(field) and input_flag == 'create')
185+
186+
182187
@convert_django_field.register(models.DecimalField)
183188
@convert_django_field.register(models.FloatField)
184189
@convert_django_field.register(models.DurationField)

0 commit comments

Comments
 (0)