How to filter a query by a list of ids in GraphQL using graphene-django?

graphene-django-filter
graphql filter
graphql multiple filters
graphene list
graphene python
graphene-django exclude fields
graphene list input
graphene object type

I'm trying to perform a GraphQL query using Django and Graphene. To query one single object using the id I did the following:

{
  samples(id:"U2FtcGxlU2V0VHlwZToxMjYw") {
    edges {
      nodes {
        name
      }
    }
  }
}

And it just works fine. Problem arise when I try to query with more than one id, like the following:

{
  samples(id_In:"U2FtcGxlU2V0VHlwZToxMjYw, U2FtcGxlU2V0VHlwZToxMjYx") {
    edges {
      nodes {
        name
      }
    }
  }
} 

In the latter case I got the following error:

argument should be a bytes-like object or ASCII string, not 'list'

And this is a sketch of how defined the Type and Query in django-graphene

class SampleType(DjangoObjectType):
  class Meta:
    model = Sample
    filter_fields = {
      'id': ['exact', 'in'],
     }
     interfaces = (graphene.relay.Node,)

class Query(object):
  samples = DjangoFilterConnectionField(SampleType)

  def resolve_sample_sets(self, info, **kwargs):
    return Sample.objects.all()

GlobalIDMultipleChoiceFilter from django-graphene kinda solves this issue, if you put "in" in the field name. You can create filters like

from django_filters import FilterSet
from graphene_django.filter import GlobalIDMultipleChoiceFilter

class BookFilter(FilterSet):
    author = GlobalIDMultipleChoiceFilter()

and use it by

{
  books(author: ["<GlobalID1>", "<GlobalID2>"]) {
    edges {
      nodes {
        name
      }
    }
  }
}

Still not perfect, but the need for custom code is minimized.

Filtering, Graphene-Django integrates with django-filter (2.x for Python 3 or 1.x for query { # Note that fields names become camelcased allAnimals(genus: "cat", become camelcased allAnimals(name_Icontains: "lion") { edges { node { id, name } } } }  A filter argument is added to field arguments, as well as input types used to support them. Filtering is currently supported for scalar fields, enums, @relation fields and types. Filtering on @cypher directive fields is not yet supported. #filter Argument. The auto-generated filter argument is used to support complex filtering in queries. For

I had trouble implementing the 'in' filter as well--it appears to be misimplemented in graphene-django right now and does not work as expected. Here are the steps to make it work:

  1. Remove the 'in' filter from your filter_fields
  2. Add an input value to your DjangoFilterConnectionField entitled 'id__in' and make it a list of IDs
  3. Rename your resolver to match the 'samples' field.
  4. Handle filtering by 'id__in' in your resolver for the field. For you this will look as follows:
from base64 import b64decode

def get_pk_from_node_id(node_id: str):
    """Gets pk from node_id"""
    model_with_pk = b64decode(node_id).decode('utf-8')
    model_name, pk = model_with_pk.split(":")
    return pk


class SampleType(DjangoObjectType):
    class Meta:
        model = Sample
        filter_fields = {
            'id': ['exact'],
         }
        interfaces = (graphene.relay.Node,)


class Query(object):

    samples = DjangoFilterConnectionField(SampleType, id__in=graphene.List(graphene.ID))

    def resolve_samples(self, info, **kwargs):
        # filter_field for 'in' seems to not work, this hack works
        id__in = kwargs.get('id__in')
        if id__in:
            node_ids = kwargs.pop('id__in')
            pk_list = [get_pk_from_node_id(node_id) for node_id in node_ids]
            return Sample._default_manager.filter(id__in=pk_list)
        return Sample._default_manager.all()

This will allow you to call the filter with the following api. Note the use of an actual array in the signature (I think this is a better API than sending a comma separated string of values). This solution still allows you to add other filters to the request and they will chain together correctly.

{
  samples(id_In: ["U2FtcGxlU2V0VHlwZToxMjYw", "U2FtcGxlU2V0VHlwZToxMjYx"]) {
    edges {
      nodes {
        name
      }
    }
  }
} 

Queries & ObjectTypes, Graphene-Django offers a host of features for performing GraphQL queries. String()) def resolve_questions(self, info, **kwargs): # Querying a list return class QuestionType(DjangoObjectType): class Meta: model = Question fields = ('​id', Use this to control filtering on the ObjectType level instead of the Query object  Creating your first query. GraphQL query language is all about selecting fields on objects. We start with “root” object and select events field on that. From the object returned by events we would select id, name and url fields. Creating your first mutation. The process of sending data to the server is called mutation.

You can easily use a Filter just put this with your nodes.

class ReportFileFilter(FilterSet):
    id = GlobalIDMultipleChoiceFilter()

Then in your query just use -

class Query(graphene.ObjectType):
    all_report_files = DjangoFilterConnectionField(ReportFileNode, filterset_class=ReportFileFilter)

This is for relay implementation of graphql django.

Separating django-filter from relay connection · Issue #206 · graphql , Problem Right now, the use of django-filter is tightly coupled with the use of the the two so that filtering can be applied to a normal graphql list as well. @​BenjjinF I'm experiencing this issue too with filtering on model IDs - did you find a solution? Foo filterset_class = FooFilterSet class Query(graphene. For more information and examples, including a list of all automatically generated query types, see Query Resolvers. js includes support for handling complex filtering in GraphQL queries. In either case, the operation is a simple string that a GraphQL server can parse and respond to with data in a specific format. === Auto-Generated Query Types.

None of the existing answers seemed to work for me as they were presented, however with some slight changes I managed to resolve my problem as follows:

You can create a custom FilterSet class for your object type, and filter the field by using the GlobalIDMultipleChoiceFilter. for example:

from django_filters import FilterSet
from graphene_django.filter import GlobalIDFilter, GlobalIDMultipleChoiceFilter

class SampleFilter(FilterSet):
    id = GlobalIDFilter()
    id__in = GlobalIDMultipleChoiceFilter(field_name="id")

    class Meta:
        model = Sample
        fields = (
            "id_in",
            "id",
        )

Something I came cross is that you can not have filter_fields defined with this approach. Instead, you have to only rely on the custom FilterSet class exclusively, making your object type effectively look like this:

from graphene import relay
from graphene_django import DjangoObjectType

class SampleType(DjangoObjectType):
    class Meta:
        model = Sample
        filterset_class = SampleFilter
        interfaces = (relay.Node,)

Best practices for filtering queries based on grandchildren · Issue , I am using SQLAlchemy, but not graphene-sqlalchemy as I am not using relay String() class Order(ObjectType): id = ID() line_items = List(LineItem, .com/​graphql-python/graphene-django/blob/master/docs/filtering.rst The user query returns the User object based on the passed id. The users query then returns a list of users. We have also defined the non-required enum type role, which is used in the users query as an argument for filtering the result. In this simple schema we used modifiers quite a lot. In the rest of the article we will go through these use

Graphene-Python, To limit fields in a GraphQL query simply use the only_fields meta attribute. In order to filter which objects are available in a queryset-based list, define a to id-​based node access, we need to add a method to your DjangoObjectType . In your case, the feed query in your API will accept a filter string. The query then should only return the Link elements where the url or the description contain that filter string. Next, you need to update the implementation of the feed resolver to account for the new parameter clients can provide.

graphql-python - Relay, graphql-python - Relay. Graphene and Graphene Django already comes with the Relay First of all, let's implement our link query using Relay. from graphene_django import DjangoObjectType from graphene_django.filter #3 : Each node implements an interface with an unique ID (you'll see the result of this in a bit). Automatic self-linking is supported through these Meta options: self_url specifies the URL to the resource itself. json graphql schema for graphene-django. List(graphene. 0 - a Python package on PyPI - Libraries. Schema(query=Query) Creating your first query GraphQL query language is all about selecting fields on objects.

Building a GraphQL API with Django, If we want a field to contain the list of the type, we enclose it in square brackets and Movie data by providing their ID s, or we can get a list of them without filtering​. With Graphene, we do not have to use GraphQL's syntax to create a schema, we We retrieve the ID from the query parameters and return the actor from our  This query looks similar to the feed query that’s used in LinkList. However, this time it takes in an argument called filter that will be used to constrain the list of links you want to retrieve. The actual filter is built and used in the feed resolver which is implemented in server/src/resolvers/Query.js:

Comments
  • First, you need to extend SampleType with a list field -- something like ids = graphene.List(graphene.ID())
  • @MarkChackerian could you elaborate on this and provide a solution? I've run into the same issue and can't see how adding the ids field changes anything. It seems graphene-django has some input validation issues on the in field?