Filtering now available on nodes without defining fields

This commit is contained in:
Adam Charnock 2015-12-05 11:15:17 +00:00
parent afd7aa8d72
commit 66189be4a9
7 changed files with 76 additions and 21 deletions

View File

@ -20,6 +20,7 @@ class DjangoConnectionField(ConnectionField):
class ConnectionOrListField(Field):
connection_field_class = ConnectionField
def internal_type(self, schema):
model_field = self.type
@ -27,7 +28,7 @@ class ConnectionOrListField(Field):
if not field_object_type:
raise SkipField()
if is_node(field_object_type):
field = ConnectionField(field_object_type)
field = self.connection_field_class(field_object_type)
else:
field = Field(List(field_object_type))
field.contribute_to_class(self.object_type, self.attname)

View File

@ -1,6 +1,6 @@
try:
import django_filters # noqa
except:
from graphene.contrib.django.utils import DJANGO_FILTER_INSTALLED
if not DJANGO_FILTER_INSTALLED:
raise Exception(
"Use of django filtering requires the django-filter package "
"be installed. You can do so using `pip install django-filter`"

View File

@ -1,9 +1,12 @@
from .utils import DJANGO_FILTER_INSTALLED
from ...core.classtypes.objecttype import ObjectTypeOptions
from ...relay.types import Node
from ...relay.utils import is_node
VALID_ATTRS = ('model', 'only_fields', 'exclude_fields',
'filter_fields', 'filter_order_by')
VALID_ATTRS = ('model', 'only_fields', 'exclude_fields')
if DJANGO_FILTER_INSTALLED:
VALID_ATTRS += ('filter_fields', 'filter_order_by')
class DjangoOptions(ObjectTypeOptions):

View File

@ -1,20 +1,23 @@
import pytest
pytestmark = []
from graphene import ObjectType, Schema
from graphene.contrib.django.utils import DJANGO_FILTER_INSTALLED
from graphene.relay import NodeField
try:
import django_filters
except ImportError:
pytestmark.append(pytest.mark.skipif(True, reason='django_filters not installed'))
else:
from graphene.contrib.django.filter import (GlobalIDFilter, DjangoFilterConnectionField,
GlobalIDMultipleChoiceFilter)
from graphene.contrib.django.tests.filter.filters import ArticleFilter, PetFilter
from graphene.contrib.django import DjangoNode
from graphene.contrib.django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
from graphene.contrib.django.tests.models import Article, Pet, Reporter
pytestmark = []
if DJANGO_FILTER_INSTALLED:
import django_filters
from graphene.contrib.django.filter import (GlobalIDFilter, DjangoFilterConnectionField,
GlobalIDMultipleChoiceFilter)
from graphene.contrib.django.tests.filter.filters import ArticleFilter, PetFilter
else:
pytestmark.append(pytest.mark.skipif(True, reason='django_filters not installed'))
pytestmark.append(pytest.mark.django_db)
@ -124,6 +127,32 @@ def test_filter_filterset_information_on_meta():
assert_orderable(field)
def test_filter_filterset_information_on_meta_related():
class ReporterFilterNode(DjangoNode):
class Meta:
model = Reporter
filter_fields = ['first_name', 'articles']
filter_order_by = True
class ArticleFilterNode(DjangoNode):
class Meta:
model = Article
filter_fields = ['headline', 'reporter']
filter_order_by = True
class Query(ObjectType):
all_reporters = DjangoFilterConnectionField(ReporterFilterNode)
all_articles = DjangoFilterConnectionField(ArticleFilterNode)
reporter = NodeField(ReporterFilterNode)
article = NodeField(ArticleFilterNode)
schema = Schema(query=Query)
schema.schema # Trigger the schema loading
articles_field = schema.get_type('ReporterFilterNode')._meta.fields_map['articles']
assert_arguments(articles_field, 'headline', 'reporter')
assert_orderable(articles_field)
def test_global_id_field_implicit():
field = DjangoFilterConnectionField(ArticleNode, fields=['id'])
filterset_class = field.resolver_fn.get_filterset_class()

View File

@ -1,13 +1,13 @@
import pytest
from django.core.exceptions import ImproperlyConfigured
try:
import django_filters # noqa
except ImportError:
pytestmark = pytest.mark.skipif(True, reason='django_filters not installed')
else:
from graphene.contrib.django.utils import DJANGO_FILTER_INSTALLED
if DJANGO_FILTER_INSTALLED:
from graphene.contrib.django.filter.resolvers import FilterConnectionResolver
from graphene.contrib.django.tests.filter.filters import ReporterFilter, ArticleFilter
else:
pytestmark = pytest.mark.skipif(True, reason='django_filters not installed')
from graphene.contrib.django.tests.models import Reporter, Article
from graphene.contrib.django.tests.test_resolvers import ReporterNode, ArticleNode

View File

@ -5,6 +5,7 @@ from django.db import models
from ...core.classtypes.objecttype import ObjectType, ObjectTypeMeta
from ...relay.types import Connection, Node, NodeMeta
from .utils import DJANGO_FILTER_INSTALLED
from .converter import convert_django_field
from .options import DjangoOptions
from .utils import get_reverse_fields, maybe_queryset
@ -49,6 +50,15 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
return cls
class DjangoFilterObjectTypeMeta():
def convert_django_field(cls, field):
from graphene.contrib.django.filter import DjangoFilterConnectionField
field = super(DjangoFilterObjectTypeMeta, cls).convert_django_field(field)
field.connection_field_class = DjangoFilterConnectionField
return field
class InstanceObjectType(ObjectType):
class Meta:
@ -92,7 +102,13 @@ class DjangoConnection(Connection):
return super(DjangoConnection, cls).from_list(iterable, *args, **kwargs)
class DjangoNodeMeta(DjangoObjectTypeMeta, NodeMeta):
django_node_meta_bases = (DjangoObjectTypeMeta, NodeMeta)
# Only include filter functionality if available
if DJANGO_FILTER_INSTALLED:
django_node_meta_bases = (DjangoFilterObjectTypeMeta,) + django_node_meta_bases
class DjangoNodeMeta(*django_node_meta_bases):
pass

View File

@ -7,6 +7,12 @@ from graphene.utils import LazyList
from graphene import Argument, String
try:
import django_filters # noqa
DJANGO_FILTER_INSTALLED = True
except ImportError:
DJANGO_FILTER_INSTALLED = False
def get_type_for_model(schema, model):
schema = schema