mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 01:47:45 +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):
 | 
			
		||||
    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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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`"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user