graphene-django - How to filter?
Asked Answered
S

3

23

I use graphen-django for build a GraphQL API. I have succesfully create this API, but I can't pass a argument for filter my response.

This is my models.py:

from django.db import models

class Application(models.Model):
    name = models.CharField("nom", unique=True, max_length=255)
    sonarQube_URL = models.CharField("Url SonarQube", max_length=255, blank=True, null=True)

    def __unicode__(self):
    return self.name

This is my schema.py: import graphene from graphene_django import DjangoObjectType from models import Application

class Applications(DjangoObjectType):
    class Meta:
        model = Application

class Query(graphene.ObjectType):
    applications = graphene.List(Applications)

    @graphene.resolve_only_args
    def resolve_applications(self):
        return Application.objects.all()


schema = graphene.Schema(query=Query)

My urls.py:

urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^admin/', admin.site.urls),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^api-token-auth/', authviews.obtain_auth_token),
    url(r'^graphql', GraphQLView.as_view(graphiql=True)),
]

As you can see, I also have a REST API.

My settings.py contains this:

GRAPHENE = {
    'SCHEMA': 'tibco.schema.schema'
}

I follow this: https://github.com/graphql-python/graphene-django

When I send this resquest:

{
  applications {
    name
  }
}

I've got this response:

{
  "data": {
    "applications": [
      {
        "name": "foo"
      },
      {
        "name": "bar"
      }
    ]
   }
}

So, it's works!

But when I try to pass an argument like this:

{
  applications(name: "foo") {
    name
    id
  }
}

I have this response:

{
  "errors": [
   {
      "message": "Unknown argument \"name\" on field \"applications\" of type \"Query\".",
      "locations": [
        {
          "column": 16,
          "line": 2
        }
      ]
    }
  ]
}

What i have missed? Or maybe I do something wrong?

Springlet answered 2/11, 2016 at 14:7 Comment(0)
S
21

I've found a solution thanks to: https://docs.graphene-python.org/projects/django/en/latest/

This is my answer. I have edit my schema.py:

import graphene
from graphene import relay, AbstractType, ObjectType
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from models import Application

class ApplicationNode(DjangoObjectType):
    class Meta:
        model = Application
        filter_fields = ['name', 'sonarQube_URL']
        interfaces = (relay.Node, )

class Query(ObjectType):
    application = relay.Node.Field(ApplicationNode)
    all_applications = DjangoFilterConnectionField(ApplicationNode)

schema = graphene.Schema(query=Query)

Then, it was missing a package: django-filter (https://github.com/carltongibson/django-filter/tree/master). Django-filter is used by DjangoFilterConnectionField.

Now I can do this:

query {
  allApplications(name: "Foo") {
    edges {
      node {
        name
      }
    }
  }
}

and the response will be:

{
  "data": {
    "allApplications": {
      "edges": [
        {
          "node": {
            "name": "Foo"
          }
        }
      ]
    }
  }
}
Springlet answered 3/11, 2016 at 14:2 Comment(0)
W
6

If you're in my case and don't want to use Relay, you can also handle filtering directly in you resolvers using Django orm filtering. Example here: Filter graphql query in django

Wilber answered 26/3, 2020 at 15:21 Comment(1)
It's insane that there's a coupling to replay in the otherwise-generic sounding DjangoListFieldMeyerbeer
I
4

Little addition to Adrien Answer. If you want to perform different operation while filtering like contains and exact match then edit your schema.py

class ApplicationNode(DjangoObjectType):
    class Meta:
        model = Application
        # Provide more complex lookup types
        filter_fields = {
            'name': ['exact', 'icontains', 'istartswith']
        }
        interfaces = (relay.Node, )

and you can write the query like this

  query {
  allApplications(name_Icontains: "test") {
    edges {
      node {
        id,
        name
      }
    }
  }
}
Imminent answered 14/2, 2021 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.