Skip to content

Commit aa30750

Browse files
jkimbomvanlonden
authored andcommitted
Bugfix: Correct filter types for DjangoFilterConnectionFields (#682)
* Get form field from Django model before defaulting to django-filter * Add test * Cleanup some flake8 warnings and pytest warnings * Run isort and add black compatible config
1 parent 9aabe2c commit aa30750

File tree

3 files changed

+85
-12
lines changed

3 files changed

+85
-12
lines changed

graphene_django/filter/tests/test_fields.py

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
from datetime import datetime
2+
from textwrap import dedent
23

34
import pytest
5+
from django.db.models import TextField, Value
6+
from django.db.models.functions import Concat
47

5-
from graphene import Field, ObjectType, Schema, Argument, Float, Boolean, String
8+
from graphene import Argument, Boolean, Field, Float, ObjectType, Schema, String
69
from graphene.relay import Node
710
from graphene_django import DjangoObjectType
811
from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
912
from graphene_django.tests.models import Article, Pet, Reporter
1013
from graphene_django.utils import DJANGO_FILTER_INSTALLED
1114

12-
# for annotation test
13-
from django.db.models import TextField, Value
14-
from django.db.models.functions import Concat
15-
1615
pytestmark = []
1716

1817
if DJANGO_FILTER_INSTALLED:
@@ -183,7 +182,7 @@ class context(object):
183182
}
184183
"""
185184
schema = Schema(query=Query)
186-
result = schema.execute(query, context_value=context())
185+
result = schema.execute(query, context=context())
187186
assert not result.errors
188187

189188
assert len(result.data["contextArticles"]["edges"]) == 1
@@ -462,15 +461,15 @@ class Meta:
462461
class Query(ObjectType):
463462
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)
464463

465-
r1 = Reporter.objects.create(
464+
Reporter.objects.create(
466465
first_name="A test user", last_name="Last Name", email="test1@test.com"
467466
)
468-
r2 = Reporter.objects.create(
467+
Reporter.objects.create(
469468
first_name="Other test user",
470469
last_name="Other Last Name",
471470
email="test2@test.com",
472471
)
473-
r3 = Reporter.objects.create(
472+
Reporter.objects.create(
474473
first_name="Random", last_name="RandomLast", email="random@test.com"
475474
)
476475

@@ -638,7 +637,7 @@ def resolve_all_reporters(self, info, **args):
638637
Reporter.objects.create(
639638
first_name="Bob", last_name="Doe", email="bobdoe@example.com", a_choice=2
640639
)
641-
r = Reporter.objects.create(
640+
Reporter.objects.create(
642641
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
643642
)
644643

@@ -684,7 +683,7 @@ def resolve_all_reporters(self, info, reverse_order=False, **args):
684683
return reporters
685684

686685
Reporter.objects.create(first_name="b")
687-
r = Reporter.objects.create(first_name="a")
686+
Reporter.objects.create(first_name="a")
688687

689688
schema = Schema(query=Query)
690689
query = """
@@ -767,3 +766,55 @@ def resolve_all_reporters(self, info, **args):
767766

768767
assert not result.errors
769768
assert result.data == expected
769+
770+
771+
def test_integer_field_filter_type():
772+
class PetType(DjangoObjectType):
773+
class Meta:
774+
model = Pet
775+
interfaces = (Node,)
776+
filter_fields = {"age": ["exact"]}
777+
only_fields = ["age"]
778+
779+
class Query(ObjectType):
780+
pets = DjangoFilterConnectionField(PetType)
781+
782+
schema = Schema(query=Query)
783+
784+
assert str(schema) == dedent(
785+
"""\
786+
schema {
787+
query: Query
788+
}
789+
790+
interface Node {
791+
id: ID!
792+
}
793+
794+
type PageInfo {
795+
hasNextPage: Boolean!
796+
hasPreviousPage: Boolean!
797+
startCursor: String
798+
endCursor: String
799+
}
800+
801+
type PetType implements Node {
802+
age: Int!
803+
id: ID!
804+
}
805+
806+
type PetTypeConnection {
807+
pageInfo: PageInfo!
808+
edges: [PetTypeEdge]!
809+
}
810+
811+
type PetTypeEdge {
812+
node: PetType
813+
cursor: String!
814+
}
815+
816+
type Query {
817+
pets(before: String, after: String, first: Int, last: Int, age: Int): PetTypeConnection
818+
}
819+
"""
820+
)

graphene_django/filter/utils.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,25 @@ def get_filtering_args_from_filterset(filterset_class, type):
1111
from ..forms.converter import convert_form_field
1212

1313
args = {}
14+
model = filterset_class._meta.model
1415
for name, filter_field in six.iteritems(filterset_class.base_filters):
15-
field_type = convert_form_field(filter_field.field).Argument()
16+
if name in filterset_class.declared_filters:
17+
form_field = filter_field.field
18+
else:
19+
field_name = name.split("__", 1)[0]
20+
model_field = model._meta.get_field(field_name)
21+
22+
if hasattr(model_field, "formfield"):
23+
form_field = model_field.formfield(
24+
required=filter_field.extra.get("required", False)
25+
)
26+
27+
# Fallback to field defined on filter if we can't get it from the
28+
# model field
29+
if not form_field:
30+
form_field = filter_field.field
31+
32+
field_type = convert_form_field(form_field).Argument()
1633
field_type.description = filter_field.label
1734
args[name] = field_type
1835

setup.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ omit = */tests/*
3838

3939
[isort]
4040
known_first_party=graphene,graphene_django
41+
multi_line_output=3
42+
include_trailing_comma=True
43+
force_grid_wrap=0
44+
use_parentheses=True
45+
line_length=88

0 commit comments

Comments
 (0)