mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 18:08:01 +03:00 
			
		
		
		
	Fixed filterset limit issue
This commit is contained in:
		
							parent
							
								
									055c6e2359
								
							
						
					
					
						commit
						5833cb83be
					
				| 
						 | 
				
			
			@ -46,17 +46,20 @@ class DjangoConnectionField(ConnectionField):
 | 
			
		|||
        else:
 | 
			
		||||
            return self.model._default_manager
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def connection_resolver(resolver, connection, default_manager, root, args, context, info):
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def merge_querysets(cls, default_queryset, queryset):
 | 
			
		||||
        return default_queryset & queryset
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def connection_resolver(cls, resolver, connection, default_manager, root, args, context, info):
 | 
			
		||||
        iterable = resolver(root, args, context, info)
 | 
			
		||||
        if iterable is None:
 | 
			
		||||
            iterable = default_manager
 | 
			
		||||
        iterable = maybe_queryset(iterable)
 | 
			
		||||
        if isinstance(iterable, QuerySet):
 | 
			
		||||
            if iterable is not default_manager:
 | 
			
		||||
                iterable = list(set(iterable).intersection(maybe_queryset(default_manager)))
 | 
			
		||||
                _len = len(iterable)
 | 
			
		||||
            else:
 | 
			
		||||
                default_queryset = maybe_queryset(default_manager)
 | 
			
		||||
                iterable = cls.merge_querysets(default_queryset, iterable)
 | 
			
		||||
            _len = iterable.count()
 | 
			
		||||
        else:
 | 
			
		||||
            _len = len(iterable)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,14 +45,37 @@ class DjangoFilterConnectionField(DjangoConnectionField):
 | 
			
		|||
        return get_filtering_args_from_filterset(self.filterset_class, self.node_type)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def connection_resolver(resolver, connection, default_manager, filterset_class, filtering_args,
 | 
			
		||||
    def merge_querysets(default_queryset, queryset):
 | 
			
		||||
        # There could be the case where the default queryset (returned from the filterclass)
 | 
			
		||||
        # and the resolver queryset have some limits on it.
 | 
			
		||||
        # We only would be able to apply one of those, but not both
 | 
			
		||||
        # at the same time.
 | 
			
		||||
 | 
			
		||||
        # See related PR: https://github.com/graphql-python/graphene-django/pull/126
 | 
			
		||||
 | 
			
		||||
        assert not (default_queryset.query.low_mark and queryset.query.low_mark), (
 | 
			
		||||
            'Received two sliced querysets (low mark) in the connection, please slice only in one.'
 | 
			
		||||
        )
 | 
			
		||||
        assert not (default_queryset.query.high_mark and queryset.query.high_mark), (
 | 
			
		||||
            'Received two sliced querysets (high mark) in the connection, please slice only in one.'
 | 
			
		||||
        )
 | 
			
		||||
        low = default_queryset.query.low_mark or queryset.query.low_mark
 | 
			
		||||
        high = default_queryset.query.high_mark or queryset.query.high_mark
 | 
			
		||||
        default_queryset.query.clear_limits()
 | 
			
		||||
        queryset = default_queryset & queryset
 | 
			
		||||
        queryset.query.set_limits(low, high)
 | 
			
		||||
        return queryset
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def connection_resolver(cls, resolver, connection, default_manager, filterset_class, filtering_args,
 | 
			
		||||
                            root, args, context, info):
 | 
			
		||||
        filter_kwargs = {k: v for k, v in args.items() if k in filtering_args}
 | 
			
		||||
        qs = filterset_class(
 | 
			
		||||
            data=filter_kwargs,
 | 
			
		||||
            queryset=default_manager.get_queryset()
 | 
			
		||||
        ).qs
 | 
			
		||||
        return DjangoConnectionField.connection_resolver(resolver, connection, qs, root, args, context, info)
 | 
			
		||||
        return super(DjangoFilterConnectionField, cls).connection_resolver(
 | 
			
		||||
            resolver, connection, qs, root, args, context, info)
 | 
			
		||||
 | 
			
		||||
    def get_resolver(self, parent_resolver):
 | 
			
		||||
        return partial(self.connection_resolver, parent_resolver, self.type, self.get_manager(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -525,10 +525,12 @@ def test_should_query_filter_node_limit():
 | 
			
		|||
                edges {
 | 
			
		||||
                    node {
 | 
			
		||||
                        id
 | 
			
		||||
                        firstName
 | 
			
		||||
                        articles(lang: "es") {
 | 
			
		||||
                            edges {
 | 
			
		||||
                                node {
 | 
			
		||||
                                    id
 | 
			
		||||
                                    lang
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			@ -542,11 +544,13 @@ def test_should_query_filter_node_limit():
 | 
			
		|||
        'allReporters': {
 | 
			
		||||
            'edges': [{
 | 
			
		||||
                'node': {
 | 
			
		||||
                    'id': 'UmVwb3J0ZXJUeXBlOjE=',
 | 
			
		||||
                    'id': 'UmVwb3J0ZXJUeXBlOjI=',
 | 
			
		||||
                    'firstName': 'John',
 | 
			
		||||
                    'articles': {
 | 
			
		||||
                        'edges': [{
 | 
			
		||||
                            'node': {
 | 
			
		||||
                                'id': 'QXJ0aWNsZVR5cGU6MQ=='
 | 
			
		||||
                                'id': 'QXJ0aWNsZVR5cGU6MQ==',
 | 
			
		||||
                                'lang': 'ES'
 | 
			
		||||
                            }
 | 
			
		||||
                        }]
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -558,3 +562,63 @@ def test_should_query_filter_node_limit():
 | 
			
		|||
    result = schema.execute(query)
 | 
			
		||||
    assert not result.errors
 | 
			
		||||
    assert result.data == expected
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_should_query_filter_node_double_limit_raises():
 | 
			
		||||
    class ReporterFilter(FilterSet):
 | 
			
		||||
        limit = NumberFilter(method='filter_limit')
 | 
			
		||||
 | 
			
		||||
        def filter_limit(self, queryset, name, value):
 | 
			
		||||
            return queryset[:value]
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = Reporter
 | 
			
		||||
            fields = ['first_name', ]
 | 
			
		||||
 | 
			
		||||
    class ReporterType(DjangoObjectType):
 | 
			
		||||
 | 
			
		||||
        class Meta:
 | 
			
		||||
            model = Reporter
 | 
			
		||||
            interfaces = (Node, )
 | 
			
		||||
 | 
			
		||||
    class Query(graphene.ObjectType):
 | 
			
		||||
        all_reporters = DjangoFilterConnectionField(
 | 
			
		||||
            ReporterType,
 | 
			
		||||
            filterset_class=ReporterFilter
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        def resolve_all_reporters(self, args, context, info):
 | 
			
		||||
            return Reporter.objects.order_by('a_choice')[:2]
 | 
			
		||||
 | 
			
		||||
    Reporter.objects.create(
 | 
			
		||||
        first_name='Bob',
 | 
			
		||||
        last_name='Doe',
 | 
			
		||||
        email='bobdoe@example.com',
 | 
			
		||||
        a_choice=2
 | 
			
		||||
    )
 | 
			
		||||
    r = Reporter.objects.create(
 | 
			
		||||
        first_name='John',
 | 
			
		||||
        last_name='Doe',
 | 
			
		||||
        email='johndoe@example.com',
 | 
			
		||||
        a_choice=1
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    schema = graphene.Schema(query=Query)
 | 
			
		||||
    query = '''
 | 
			
		||||
        query NodeFilteringQuery {
 | 
			
		||||
            allReporters(limit: 1) {
 | 
			
		||||
                edges {
 | 
			
		||||
                    node {
 | 
			
		||||
                        id
 | 
			
		||||
                        firstName
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    result = schema.execute(query)
 | 
			
		||||
    assert len(result.errors) == 1
 | 
			
		||||
    assert str(result.errors[0]) == (
 | 
			
		||||
        'Received two sliced querysets (high mark) in the connection, please slice only in one.'
 | 
			
		||||
    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user