Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions graphene_django/filter/fields.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from collections import OrderedDict
from functools import partial

from graphql.error import GraphQLError
from graphene.types.argument import to_arguments
from ..fields import DjangoConnectionField
from .utils import get_filtering_args_from_filterset, get_filterset_class
Expand Down Expand Up @@ -89,11 +90,22 @@ def connection_resolver(
**args
):
filter_kwargs = {k: v for k, v in args.items() if k in filtering_args}
qs = filterset_class(

filterset = filterset_class(
data=filter_kwargs,
queryset=default_manager.get_queryset(),
request=info.context,
).qs
)

if not (filterset.is_bound and filterset.form.is_valid()):
exc = {
str(key): [str(e.message) for e in error_list]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key here is in Python/Django source casing I believe. I think we could improve the error reporting here anyway (see other comment), but if we do want to send these to the client, they should use the field names as in the API – i.e. probably camelCase names, although I believe this can be configured per schema, and overridden per field.

for key, error_list in filterset.form.errors.as_data().items()
}

raise GraphQLError(exc)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're passing a dictionary here, but GraphQLError appears to take a str. Should we format this into a string? I'm not sure that relying on the stringifying behaviour of GraphQLError is the right thing to do.

One alternative would be to wrap up the dict -> str processing in a GraphQLDjangoFilterError (better name needed). This would:

a) make the code here simpler
b) make it easier to customise the behaviour in the view the API that lets the Django view intercept errors.


qs = filterset.qs

return super(DjangoFilterConnectionField, cls).connection_resolver(
resolver,
Expand Down
31 changes: 31 additions & 0 deletions graphene_django/filter/tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,37 @@ class Query(ObjectType):
)


def test_filter_filterset_validation_errors():
class ReporterFilterNode(DjangoObjectType):
class Meta:
model = Reporter
interfaces = (Node,)
filter_fields = ("id",)

class Query(ObjectType):
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)

r1 = Reporter.objects.create(first_name="r1", last_name="r1", email="r1@test.com")

query = """
query {
allReporters(id:"foo") {
edges {
node {
id
}
}
}
}
"""
schema = Schema(query=Query)
result = schema.execute(query)

assert result.errors
# We should get back an error message
assert result.to_dict()['errors'][0]["message"] == "{'id': ['Invalid ID specified.']}"


def test_global_id_field_implicit():
field = DjangoFilterConnectionField(ArticleNode, fields=["id"])
filterset_class = field.filterset_class
Expand Down