Skip to content

Commit f20fbc2

Browse files
committed
Merge remote-tracking branch 'origin/bugfix/multiple_model_serializers' into bugfix/multiple_model_serializers
# Conflicts: # graphene_django/rest_framework/mutation.py # graphene_django/tests/test_converter.py # graphene_django/types.py # graphene_django/utils/utils.py # graphene_django/views.py
2 parents 557d37d + f45f1ae commit f20fbc2

File tree

18 files changed

+646
-118
lines changed

18 files changed

+646
-118
lines changed

.circleci/config.yml

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Python CircleCI 2.0 configuration file
2+
#
3+
# Check https://circleci.com/docs/2.0/language-python/ for more details
4+
#
5+
version: 2.1
6+
7+
jobs:
8+
test-3_7-django2_1: &test-template
9+
parameters:
10+
django_version:
11+
type: string
12+
default: "2.1"
13+
docker:
14+
# specify the version you desire here
15+
# use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers`
16+
- image: circleci/python:3.7-rc-node
17+
18+
# Specify service dependencies here if necessary
19+
# CircleCI maintains a library of pre-built images
20+
# documented at https://circleci.com/docs/2.0/circleci-images/
21+
# - image: circleci/postgres:9.4
22+
23+
working_directory: ~/repo
24+
25+
steps:
26+
- checkout
27+
28+
# Download and cache dependencies
29+
- restore_cache:
30+
keys:
31+
- v1-dependencies-{{ checksum "setup.py" }}
32+
- v1-dependencies-
33+
34+
- run:
35+
name: install dependencies
36+
command: |
37+
python3 -m venv venv
38+
. venv/bin/activate
39+
pip install -e .[test]
40+
pip install psycopg2
41+
42+
- run:
43+
name: install django version
44+
command: |
45+
python3 -m venv venv
46+
. venv/bin/activate
47+
pip install django==<< parameters.django_version >>
48+
49+
- save_cache:
50+
paths:
51+
- ./venv
52+
key: v1-dependencies-{{ checksum "setup.py" }}
53+
54+
- run:
55+
name: Run tests
56+
command: |
57+
. venv/bin/activate
58+
py.test --cov=graphene_django graphene_django examples
59+
coveralls
60+
61+
- store_artifacts:
62+
path: test-reports
63+
destination: test-reports
64+
65+
test-3_7-django2_0:
66+
<<: *test-template
67+
docker:
68+
- image: circleci/python:3.7-rc-node
69+
test-3_6-django2_1:
70+
<<: *test-template
71+
docker:
72+
- image: circleci/python:3.6-jessie
73+
test-3_6-django2_0:
74+
<<: *test-template
75+
docker:
76+
- image: circleci/python:3.6-jessie
77+
test-3_5-django2_1:
78+
<<: *test-template
79+
docker:
80+
- image: circleci/python:3.5-jessie
81+
test-3_5-django2_0:
82+
<<: *test-template
83+
docker:
84+
- image: circleci/python:3.5-jessie
85+
test-3_5-django1_11:
86+
<<: *test-template
87+
docker:
88+
- image: circleci/python:3.5-jessie
89+
test-3_4-django2_0:
90+
<<: *test-template
91+
docker:
92+
- image: circleci/python:3.4-jessie
93+
test-3_4-django1_11:
94+
<<: *test-template
95+
docker:
96+
- image: circleci/python:3.4-jessie
97+
# test-2_7-django1_11:
98+
# <<: *test-template
99+
# docker:
100+
# - image: circleci/python:2.7-jessie
101+
102+
workflows:
103+
version: 2
104+
test:
105+
jobs:
106+
- test-3_7-django2_1:
107+
django_version: "2.1"
108+
- test-3_7-django2_0:
109+
django_version: "2.0"
110+
- test-3_6-django2_1:
111+
django_version: "2.1"
112+
- test-3_6-django2_0:
113+
django_version: "2.0"
114+
- test-3_5-django2_1:
115+
django_version: "2.1"
116+
- test-3_5-django2_0:
117+
django_version: "2.0"
118+
- test-3_5-django1_11:
119+
django_version: "1.11"
120+
- test-3_4-django2_0:
121+
django_version: "2.0"
122+
- test-3_4-django2_0:
123+
django_version: "2.0"
124+
- test-3_4-django1_11:
125+
django_version: "1.11"
126+
# - test-2_7-django1_11:
127+
# django_version: "1.11"

.circleci/run-build-locally.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
curl --user ${CIRCLE_TOKEN}: \
3+
--request POST \
4+
--form revision=<commit hash>\
5+
6+
--form notify=false \
7+
https://circleci.com/api/v1.1/project/<source, eg. github>/<user name>/<project name>/tree/<branch name>

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ __pycache__/
1111
# Distribution / packaging
1212
.Python
1313
env/
14+
venv/
1415
build/
1516
develop-eggs/
1617
dist/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Please read [UPGRADE-v2.0.md](https://github.com/graphql-python/graphene/blob/ma
22

33
---
44

5-
# ![Graphene Logo](http://graphene-python.org/favicon.png) Graphene-Django [![Build Status](https://travis-ci.org/graphql-python/graphene-django.svg?branch=master)](https://travis-ci.org/graphql-python/graphene-django) [![PyPI version](https://badge.fury.io/py/graphene-django.svg)](https://badge.fury.io/py/graphene-django) [![Coverage Status](https://coveralls.io/repos/graphql-python/graphene-django/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-python/graphene-django?branch=master)
5+
# ![Graphene Logo](http://graphene-python.org/favicon.png) Graphene-Django-MrMilu [![CircleCI](https://circleci.com/gh/mrmilu/graphene-django/tree/master.svg?style=svg)](https://circleci.com/gh/mrmilu/graphene-django/tree/master) [![Coverage Status](https://coveralls.io/repos/mrmilu/graphene-django/badge.svg?branch=master&service=github)](https://coveralls.io/github/mrmilu/graphene-django?branch=master)
66

77

88
A [Django](https://www.djangoproject.com/) integration for [Graphene](http://graphene-python.org/).

graphene_django/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .types import DjangoObjectType
22
from .fields import DjangoConnectionField
33

4-
__version__ = "2.2.0"
4+
__version__ = "2.3.1"
55

66
__all__ = ["__version__", "DjangoObjectType", "DjangoConnectionField"]

graphene_django/converter.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from .compat import ArrayField, HStoreField, JSONField, RangeField
2525
from .fields import DjangoListField, DjangoConnectionField
2626
from .utils import import_single_dispatch
27+
from .settings import graphene_settings
2728

2829
singledispatch = import_single_dispatch()
2930

@@ -58,7 +59,7 @@ def convert_django_field_with_choices(field, registry=None):
5859
if converted:
5960
return converted
6061
choices = getattr(field, "choices", None)
61-
if choices:
62+
if choices and graphene_settings.GRAPHENE_CONVERT_CHOICES_TO_ENUMS:
6263
meta = field.model._meta
6364
name = to_camel_case("{}_{}".format(meta.object_name, field.name))
6465
choices = list(get_choices(choices))
@@ -211,10 +212,10 @@ def dynamic_type():
211212

212213
@convert_django_field.register(ArrayField)
213214
def convert_postgres_array_to_list(field, registry=None):
214-
base_type = convert_django_field(field.base_field)
215-
if not isinstance(base_type, (List, NonNull)):
216-
base_type = type(base_type)
217-
return List(base_type, description=field.help_text, required=not field.null)
215+
inner_type = convert_django_field(field.base_field)
216+
if not isinstance(inner_type, (List, NonNull)):
217+
inner_type = NonNull(type(inner_type)) if inner_type.kwargs['required'] else type(inner_type)
218+
return List(inner_type, description=field.help_text, required=not field.null)
218219

219220

220221
@convert_django_field.register(HStoreField)
@@ -227,5 +228,5 @@ def convert_posgres_field_to_string(field, registry=None):
227228
def convert_posgres_range_to_string(field, registry=None):
228229
inner_type = convert_django_field(field.base_field)
229230
if not isinstance(inner_type, (List, NonNull)):
230-
inner_type = type(inner_type)
231+
inner_type = NonNull(type(inner_type)) if inner_type.kwargs['required'] else type(inner_type)
231232
return List(inner_type, description=field.help_text, required=not field.null)

graphene_django/filter/fields.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from collections import OrderedDict
22
from functools import partial
33

4+
from graphql.error import GraphQLError
45
from graphene.types.argument import to_arguments
56
from ..fields import DjangoConnectionField
67
from .utils import get_filtering_args_from_filterset, get_filterset_class
@@ -89,11 +90,22 @@ def connection_resolver(
8990
**args
9091
):
9192
filter_kwargs = {k: v for k, v in args.items() if k in filtering_args}
92-
qs = filterset_class(
93+
94+
filterset = filterset_class(
9395
data=filter_kwargs,
9496
queryset=default_manager.get_queryset(),
9597
request=info.context,
96-
).qs
98+
)
99+
100+
if not (filterset.is_bound and filterset.form.is_valid()):
101+
exc = {
102+
str(key): [str(e.message) for e in error_list]
103+
for key, error_list in filterset.form.errors.as_data().items()
104+
}
105+
106+
raise GraphQLError(exc)
107+
108+
qs = filterset.qs
97109

98110
return super(DjangoFilterConnectionField, cls).connection_resolver(
99111
resolver,

graphene_django/filter/tests/test_fields.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,37 @@ class Query(ObjectType):
290290
)
291291

292292

293+
def test_filter_filterset_validation_errors():
294+
class ReporterFilterNode(DjangoObjectType):
295+
class Meta:
296+
model = Reporter
297+
interfaces = (Node,)
298+
filter_fields = ("id",)
299+
300+
class Query(ObjectType):
301+
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)
302+
303+
r1 = Reporter.objects.create(first_name="r1", last_name="r1", email="[email protected]")
304+
305+
query = """
306+
query {
307+
allReporters(id:"foo") {
308+
edges {
309+
node {
310+
id
311+
}
312+
}
313+
}
314+
}
315+
"""
316+
schema = Schema(query=Query)
317+
result = schema.execute(query)
318+
319+
assert result.errors
320+
# We should get back an error message
321+
assert result.to_dict()['errors'][0]["message"] == "{'id': ['Invalid ID specified.']}"
322+
323+
293324
def test_global_id_field_implicit():
294325
field = DjangoFilterConnectionField(ArticleNode, fields=["id"])
295326
filterset_class = field.filterset_class

graphene_django/rest_framework/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@
44
class MyFakeModel(models.Model):
55
cool_name = models.CharField(max_length=50)
66
created = models.DateTimeField(auto_now_add=True)
7+
8+
9+
class MyFakeModelWithPassword(models.Model):
10+
cool_name = models.CharField(max_length=50)
11+
password = models.CharField(max_length=50)

0 commit comments

Comments
 (0)