mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-11 12:16:58 +03:00
Filtering now available on nodes without defining fields
This commit is contained in:
parent
afd7aa8d72
commit
66189be4a9
|
@ -20,6 +20,7 @@ class DjangoConnectionField(ConnectionField):
|
||||||
|
|
||||||
|
|
||||||
class ConnectionOrListField(Field):
|
class ConnectionOrListField(Field):
|
||||||
|
connection_field_class = ConnectionField
|
||||||
|
|
||||||
def internal_type(self, schema):
|
def internal_type(self, schema):
|
||||||
model_field = self.type
|
model_field = self.type
|
||||||
|
@ -27,7 +28,7 @@ class ConnectionOrListField(Field):
|
||||||
if not field_object_type:
|
if not field_object_type:
|
||||||
raise SkipField()
|
raise SkipField()
|
||||||
if is_node(field_object_type):
|
if is_node(field_object_type):
|
||||||
field = ConnectionField(field_object_type)
|
field = self.connection_field_class(field_object_type)
|
||||||
else:
|
else:
|
||||||
field = Field(List(field_object_type))
|
field = Field(List(field_object_type))
|
||||||
field.contribute_to_class(self.object_type, self.attname)
|
field.contribute_to_class(self.object_type, self.attname)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
try:
|
from graphene.contrib.django.utils import DJANGO_FILTER_INSTALLED
|
||||||
import django_filters # noqa
|
|
||||||
except:
|
if not DJANGO_FILTER_INSTALLED:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Use of django filtering requires the django-filter package "
|
"Use of django filtering requires the django-filter package "
|
||||||
"be installed. You can do so using `pip install django-filter`"
|
"be installed. You can do so using `pip install django-filter`"
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
from .utils import DJANGO_FILTER_INSTALLED
|
||||||
from ...core.classtypes.objecttype import ObjectTypeOptions
|
from ...core.classtypes.objecttype import ObjectTypeOptions
|
||||||
from ...relay.types import Node
|
from ...relay.types import Node
|
||||||
from ...relay.utils import is_node
|
from ...relay.utils import is_node
|
||||||
|
|
||||||
VALID_ATTRS = ('model', 'only_fields', 'exclude_fields',
|
VALID_ATTRS = ('model', 'only_fields', 'exclude_fields')
|
||||||
'filter_fields', 'filter_order_by')
|
|
||||||
|
if DJANGO_FILTER_INSTALLED:
|
||||||
|
VALID_ATTRS += ('filter_fields', 'filter_order_by')
|
||||||
|
|
||||||
|
|
||||||
class DjangoOptions(ObjectTypeOptions):
|
class DjangoOptions(ObjectTypeOptions):
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
import pytest
|
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 import DjangoNode
|
||||||
from graphene.contrib.django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
|
from graphene.contrib.django.forms import GlobalIDFormField, GlobalIDMultipleChoiceField
|
||||||
from graphene.contrib.django.tests.models import Article, Pet, Reporter
|
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)
|
pytestmark.append(pytest.mark.django_db)
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,6 +127,32 @@ def test_filter_filterset_information_on_meta():
|
||||||
assert_orderable(field)
|
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():
|
def test_global_id_field_implicit():
|
||||||
field = DjangoFilterConnectionField(ArticleNode, fields=['id'])
|
field = DjangoFilterConnectionField(ArticleNode, fields=['id'])
|
||||||
filterset_class = field.resolver_fn.get_filterset_class()
|
filterset_class = field.resolver_fn.get_filterset_class()
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import pytest
|
import pytest
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
try:
|
from graphene.contrib.django.utils import DJANGO_FILTER_INSTALLED
|
||||||
import django_filters # noqa
|
|
||||||
except ImportError:
|
if DJANGO_FILTER_INSTALLED:
|
||||||
pytestmark = pytest.mark.skipif(True, reason='django_filters not installed')
|
|
||||||
else:
|
|
||||||
from graphene.contrib.django.filter.resolvers import FilterConnectionResolver
|
from graphene.contrib.django.filter.resolvers import FilterConnectionResolver
|
||||||
from graphene.contrib.django.tests.filter.filters import ReporterFilter, ArticleFilter
|
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.models import Reporter, Article
|
||||||
from graphene.contrib.django.tests.test_resolvers import ReporterNode, ArticleNode
|
from graphene.contrib.django.tests.test_resolvers import ReporterNode, ArticleNode
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.db import models
|
||||||
|
|
||||||
from ...core.classtypes.objecttype import ObjectType, ObjectTypeMeta
|
from ...core.classtypes.objecttype import ObjectType, ObjectTypeMeta
|
||||||
from ...relay.types import Connection, Node, NodeMeta
|
from ...relay.types import Connection, Node, NodeMeta
|
||||||
|
from .utils import DJANGO_FILTER_INSTALLED
|
||||||
from .converter import convert_django_field
|
from .converter import convert_django_field
|
||||||
from .options import DjangoOptions
|
from .options import DjangoOptions
|
||||||
from .utils import get_reverse_fields, maybe_queryset
|
from .utils import get_reverse_fields, maybe_queryset
|
||||||
|
@ -49,6 +50,15 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
|
||||||
return cls
|
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 InstanceObjectType(ObjectType):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -92,7 +102,13 @@ class DjangoConnection(Connection):
|
||||||
return super(DjangoConnection, cls).from_list(iterable, *args, **kwargs)
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,12 @@ from graphene.utils import LazyList
|
||||||
|
|
||||||
from graphene import Argument, String
|
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):
|
def get_type_for_model(schema, model):
|
||||||
schema = schema
|
schema = schema
|
||||||
|
|
Loading…
Reference in New Issue
Block a user