mirror of
https://github.com/graphql-python/graphene-django.git
synced 2024-11-25 19:14:11 +03:00
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
This commit is contained in:
parent
9aabe2cbe6
commit
aa30750d39
|
@ -1,18 +1,17 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from django.db.models import TextField, Value
|
||||||
|
from django.db.models.functions import Concat
|
||||||
|
|
||||||
from graphene import Field, ObjectType, Schema, Argument, Float, Boolean, String
|
from graphene import Argument, Boolean, Field, Float, ObjectType, Schema, String
|
||||||
from graphene.relay import Node
|
from graphene.relay import Node
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
|
from graphene_django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
|
||||||
from graphene_django.tests.models import Article, Pet, Reporter
|
from graphene_django.tests.models import Article, Pet, Reporter
|
||||||
from graphene_django.utils import DJANGO_FILTER_INSTALLED
|
from graphene_django.utils import DJANGO_FILTER_INSTALLED
|
||||||
|
|
||||||
# for annotation test
|
|
||||||
from django.db.models import TextField, Value
|
|
||||||
from django.db.models.functions import Concat
|
|
||||||
|
|
||||||
pytestmark = []
|
pytestmark = []
|
||||||
|
|
||||||
if DJANGO_FILTER_INSTALLED:
|
if DJANGO_FILTER_INSTALLED:
|
||||||
|
@ -183,7 +182,7 @@ def test_filter_shortcut_filterset_context():
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
schema = Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
result = schema.execute(query, context_value=context())
|
result = schema.execute(query, context=context())
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
|
|
||||||
assert len(result.data["contextArticles"]["edges"]) == 1
|
assert len(result.data["contextArticles"]["edges"]) == 1
|
||||||
|
@ -462,15 +461,15 @@ def test_filter_filterset_related_results_with_filter():
|
||||||
class Query(ObjectType):
|
class Query(ObjectType):
|
||||||
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)
|
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)
|
||||||
|
|
||||||
r1 = Reporter.objects.create(
|
Reporter.objects.create(
|
||||||
first_name="A test user", last_name="Last Name", email="test1@test.com"
|
first_name="A test user", last_name="Last Name", email="test1@test.com"
|
||||||
)
|
)
|
||||||
r2 = Reporter.objects.create(
|
Reporter.objects.create(
|
||||||
first_name="Other test user",
|
first_name="Other test user",
|
||||||
last_name="Other Last Name",
|
last_name="Other Last Name",
|
||||||
email="test2@test.com",
|
email="test2@test.com",
|
||||||
)
|
)
|
||||||
r3 = Reporter.objects.create(
|
Reporter.objects.create(
|
||||||
first_name="Random", last_name="RandomLast", email="random@test.com"
|
first_name="Random", last_name="RandomLast", email="random@test.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -638,7 +637,7 @@ def test_should_query_filter_node_double_limit_raises():
|
||||||
Reporter.objects.create(
|
Reporter.objects.create(
|
||||||
first_name="Bob", last_name="Doe", email="bobdoe@example.com", a_choice=2
|
first_name="Bob", last_name="Doe", email="bobdoe@example.com", a_choice=2
|
||||||
)
|
)
|
||||||
r = Reporter.objects.create(
|
Reporter.objects.create(
|
||||||
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
|
first_name="John", last_name="Doe", email="johndoe@example.com", a_choice=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -684,7 +683,7 @@ def test_order_by_is_perserved():
|
||||||
return reporters
|
return reporters
|
||||||
|
|
||||||
Reporter.objects.create(first_name="b")
|
Reporter.objects.create(first_name="b")
|
||||||
r = Reporter.objects.create(first_name="a")
|
Reporter.objects.create(first_name="a")
|
||||||
|
|
||||||
schema = Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
query = """
|
query = """
|
||||||
|
@ -767,3 +766,55 @@ def test_annotation_is_perserved():
|
||||||
|
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_integer_field_filter_type():
|
||||||
|
class PetType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = Pet
|
||||||
|
interfaces = (Node,)
|
||||||
|
filter_fields = {"age": ["exact"]}
|
||||||
|
only_fields = ["age"]
|
||||||
|
|
||||||
|
class Query(ObjectType):
|
||||||
|
pets = DjangoFilterConnectionField(PetType)
|
||||||
|
|
||||||
|
schema = Schema(query=Query)
|
||||||
|
|
||||||
|
assert str(schema) == dedent(
|
||||||
|
"""\
|
||||||
|
schema {
|
||||||
|
query: Query
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Node {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageInfo {
|
||||||
|
hasNextPage: Boolean!
|
||||||
|
hasPreviousPage: Boolean!
|
||||||
|
startCursor: String
|
||||||
|
endCursor: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type PetType implements Node {
|
||||||
|
age: Int!
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type PetTypeConnection {
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
edges: [PetTypeEdge]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type PetTypeEdge {
|
||||||
|
node: PetType
|
||||||
|
cursor: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
pets(before: String, after: String, first: Int, last: Int, age: Int): PetTypeConnection
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
|
@ -11,8 +11,25 @@ def get_filtering_args_from_filterset(filterset_class, type):
|
||||||
from ..forms.converter import convert_form_field
|
from ..forms.converter import convert_form_field
|
||||||
|
|
||||||
args = {}
|
args = {}
|
||||||
|
model = filterset_class._meta.model
|
||||||
for name, filter_field in six.iteritems(filterset_class.base_filters):
|
for name, filter_field in six.iteritems(filterset_class.base_filters):
|
||||||
field_type = convert_form_field(filter_field.field).Argument()
|
if name in filterset_class.declared_filters:
|
||||||
|
form_field = filter_field.field
|
||||||
|
else:
|
||||||
|
field_name = name.split("__", 1)[0]
|
||||||
|
model_field = model._meta.get_field(field_name)
|
||||||
|
|
||||||
|
if hasattr(model_field, "formfield"):
|
||||||
|
form_field = model_field.formfield(
|
||||||
|
required=filter_field.extra.get("required", False)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fallback to field defined on filter if we can't get it from the
|
||||||
|
# model field
|
||||||
|
if not form_field:
|
||||||
|
form_field = filter_field.field
|
||||||
|
|
||||||
|
field_type = convert_form_field(form_field).Argument()
|
||||||
field_type.description = filter_field.label
|
field_type.description = filter_field.label
|
||||||
args[name] = field_type
|
args[name] = field_type
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user