Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Also convert BaseCSVFilter for custom fields #1081

Merged
merged 1 commit into from
Dec 31, 2020
Merged
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
50 changes: 49 additions & 1 deletion graphene_django/filter/tests/test_in_filter.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest

from django_filters import FilterSet
from django_filters import rest_framework as filters
from graphene import ObjectType, Schema
from graphene.relay import Node
from graphene_django import DjangoObjectType
from graphene_django.tests.models import Pet
from graphene_django.tests.models import Pet, Person
from graphene_django.utils import DJANGO_FILTER_INSTALLED

pytestmark = []
Expand All @@ -28,8 +30,27 @@ class Meta:
}


class PersonFilterSet(FilterSet):
class Meta:
model = Person
fields = {}

names = filters.BaseInFilter(method="filter_names")

def filter_names(self, qs, name, value):
return qs.filter(name__in=value)


class PersonNode(DjangoObjectType):
class Meta:
model = Person
interfaces = (Node,)
filterset_class = PersonFilterSet


class Query(ObjectType):
pets = DjangoFilterConnectionField(PetNode)
people = DjangoFilterConnectionField(PersonNode)


def test_string_in_filter():
Expand Down Expand Up @@ -61,6 +82,33 @@ def test_string_in_filter():
]


def test_string_in_filter_with_filterset_class():
"""Test in filter on a string field with a custom filterset class."""
Person.objects.create(name="John")
Person.objects.create(name="Michael")
Person.objects.create(name="Angela")

schema = Schema(query=Query)

query = """
query {
people (names: ["John", "Michael"]) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Neat.

edges {
node {
name
}
}
}
}
"""
result = schema.execute(query)
assert not result.errors
assert result.data["people"]["edges"] == [
{"node": {"name": "John"}},
{"node": {"name": "Michael"}},
]


def test_int_in_filter():
"""
Test in filter on an integer field.
Expand Down
16 changes: 7 additions & 9 deletions graphene_django/filter/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def get_filtering_args_from_filterset(filterset_class, type):
model = filterset_class._meta.model
for name, filter_field in six.iteritems(filterset_class.base_filters):
form_field = None
filter_type = filter_field.lookup_expr

if name in filterset_class.declared_filters:
# Get the filter field from the explicitly declared filter
Expand All @@ -27,7 +28,6 @@ def get_filtering_args_from_filterset(filterset_class, type):
else:
# Get the filter field with no explicit type declaration
model_field = get_model_field(model, filter_field.field_name)
filter_type = filter_field.lookup_expr
if filter_type != "isnull" and hasattr(model_field, "formfield"):
form_field = model_field.formfield(
required=filter_field.extra.get("required", False)
Expand All @@ -40,10 +40,11 @@ def get_filtering_args_from_filterset(filterset_class, type):

field = convert_form_field(form_field)

if filter_type in ["in", "range"]:
# Replace CSV filters (`in`, `range`) argument type to be a list of the same type as the field.
# See comments in `replace_csv_filters` method for more details.
field = List(field.get_type())
if filter_type in ["in", "range"]:
# Replace CSV filters (`in`, `range`) argument type to be a list of
# the same type as the field. See comments in
# `replace_csv_filters` method for more details.
field = List(field.get_type())

field_type = field.Argument()
field_type.description = filter_field.label
Expand Down Expand Up @@ -79,10 +80,7 @@ def replace_csv_filters(filterset_class):
"""
for name, filter_field in six.iteritems(filterset_class.base_filters):
filter_type = filter_field.lookup_expr
if (
filter_type in ["in", "range"]
and name not in filterset_class.declared_filters
):
if filter_type in ["in", "range"]:
assert isinstance(filter_field, BaseCSVFilter)
filterset_class.base_filters[name] = Filter(
field_name=filter_field.field_name,
Expand Down
4 changes: 4 additions & 0 deletions graphene_django/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
CHOICES = ((1, "this"), (2, _("that")))


class Person(models.Model):
name = models.CharField(max_length=30)


class Pet(models.Model):
name = models.CharField(max_length=30)
age = models.PositiveIntegerField()
Expand Down